• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

LittleJoe

Win32 API e POO

51 mensagens neste tópico

Boas, mais uma vez!

A Programação Orientada ao Objecto (POO) simplifica muito as coisas (e de que maneira). Infelizmente o Win32 API não é orientado ao objecto. Estou a dar os primeiros passos em Win32 API e até já tentei incorporá-lo em classes (um pouco ingénuamente, confesso), mas, evidentemente, deu buraco.

Será que poderá haver uma espécie de "casamento" entre a POO (neste caso em C++) e o Win32 API?

Gostaria muito que me dessem a resposta...  :dontgetit:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A API do Windows é C pura.

Tipicamente fazes uma chamada às funções com a estrutura e recebes o tamanho, depois alocas a memória de acordo com o tamanho recebido para a estrutura em causa e voltas a chamar a função com essa "instância" da estrutura, e, por fim, recebes a estrutura com os valores que procuravas...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Yup. E ainda wxWidgets. E ainda Qt...

Basicamente o OOP pode servir como wrapper a praticamente qualquer tipo de código procedural. No caso de funções pode também servir como um layer separando o programador da implementação.

Pode ser tão simples como:

namespace esconder_api {

    int uma_funcao_da_api() { /* ... */ }

}

class obj {

    public:

        using namespace esconder_api;
       
        /* ... */

        int metodo() { return uma_funcao_da_api(); }

};

int main() {

    obj foo();

    foo.metodo() // chama a API uma_funcao_da_api()

}

O namespace "esconde" a API. E OOP vai agir como um wrapper e um layer, Expondo as funções e objectos da API. É assim que o MFC, WTL, WxWidgets e Qt são basicamente desenhados.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Yup. E ainda wxWidgets. E ainda Qt...

Basicamente o OOP pode servir como wrapper a praticamente qualquer tipo de código procedural. No caso de funções pode também servir como um layer separando o programador da implementação.

Pode ser tão simples como:

namespace esconder_api {

    int uma_funcao_da_api() { /* ... */ }

}

class obj {

    public:

        using namespace esconder_api;
       
        /* ... */

        int metodo() { return uma_funcao_da_api(); }

};

int main() {

    obj foo();

    foo.metodo() // chama a API uma_funcao_da_api()

}

O namespace "esconde" a API. E OOP vai agir como um wrapper e um layer, Expondo as funções e objectos da API. É assim que o MFC, WTL, WxWidgets e Qt são basicamente desenhados.

Genial. Mas também servirá para a 'int WINAPI WinMain()'?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sem dúvida. Não de forma tão simples, é claro.

Mas todas as frameworks descritas acima implementam os seus próprios pontos de entrada.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sem dúvida. Não de forma tão simples, é claro.

Mas todas as frameworks descritas acima implementam os seus próprios pontos de entrada.

Thanks!  ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Yup. E ainda wxWidgets. E ainda Qt...

Basicamente o OOP pode servir como wrapper a praticamente qualquer tipo de código procedural. No caso de funções pode também servir como um layer separando o programador da implementação.

Pode ser tão simples como:

namespace esconder_api {

    int uma_funcao_da_api() { /* ... */ }

}

class obj {

    public:

        using namespace esconder_api;
       
        /* ... */

        int metodo() { return uma_funcao_da_api(); }

};

int main() {

    obj foo();

    foo.metodo() // chama a API uma_funcao_da_api()

}

O namespace "esconde" a API. E OOP vai agir como um wrapper e um layer, Expondo as funções e objectos da API. É assim que o MFC, WTL, WxWidgets e Qt são basicamente desenhados.

Olá outra vez Marfig.

Escrevi um programa muito básico e simples que, a única coisa que faz é criar uma janela 640x480 pixels, com o intuito de tentar ilustrar a citação acima:

// Win32Classes.cpp

#include <windows.h>

namespace WndProcNameSpace
{
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
	                           WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_CLOSE:
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}

	return 0;
}
}

class WndProcClass
{
public:
LRESULT CALLBACK WProc()
{
	return (LRESULT)WndProcNameSpace::WndProc;
}
};

namespace WinMainNameSpace
{
const char g_szClassName[] = "myWindowClass";
WndProcClass wndProc; // Classe 'WndProcClass'.

int WMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                 LPSTR lpCmdLine, int nCmdShow,
                 LPCSTR windowTitle, int windowWidth, int windowHeight)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;

	//Step 1: Registering the Window Class
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = (WNDPROC)wndProc.WProc(); // 'WndProcClass wndProc'.
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!",
		                     MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	// Step 2: Creating the Window
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		g_szClassName,
		windowTitle, // Parâmetro 'windowTitle'.
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, windowWidth, windowHeight, // Parâmetros 'windowWidht' e 'windowHeight'.
		NULL, NULL, hInstance, NULL);

	if(hwnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!",
		                     MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	// Step 3: The Message Loop
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}

	return Msg.wParam;
}
}

class WinClass
{
char* title;
int width, height;

public:
WinClass(char* title, int width, int height);

int Wmain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	      LPSTR lpCmdLine, int nCmdShow)
{
	return WinMainNameSpace::WMain(hInstance, hPrevInstance,
                                                                               lpCmdLine, nCmdShow,
                                                                                                    (LPCSTR)title, width, height);
}
};

WinClass::WinClass(char* title, int width, int height)
{
this->title = title;
this->width = width;
this->height = height;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            LPSTR lpCmdLine, int nCmdShow)
{
WinClass* winClass = new WinClass("The Title of my Window", 640, 480);

winClass->Wmain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

delete winClass;
winClass = NULL;
}

O programa em si funciona, pois compilei o código fonte sem erros nem warnings. A questão é: embora muito simples e básico, será este um exemplo razoável da citação acima?

Agradecia muito que desses o teu parecer.  :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Só por curiosidade, porque não usas WTL? Fazer um wrapper a uma API desta dimensão não é tarefa fácil. :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Só por curiosidade, porque não usas WTL? Fazer um wrapper a uma API desta dimensão não é tarefa fácil. :P

Instalei o WTL, mas não funciona. Quando tento fazer a compilação dá o seguinte erro:

"fatal error C1083: Cannot open include file: 'atlbase.h': No such file or directory"

Já pensei que será por eu usar o Visual C++ 2008 Express. Será?  :dontgetit:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já pensei que será por eu usar o Visual C++ 2008 Express. Será?  :dontgetit:

Penso que sim. Pelo menos no Wiki diz o seguinte:

The freely available Microsoft Visual C++ 2005 Express Edition and Microsoft Visual C++ Codename Orcas Express Edition can be configured to handle WTL development: this requires some careful steps documented here.

Supostamente, é só seguires os passos descritos no link.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Acho que a versão 2008 Express não trás ATL, por isso tens de instalar o Platform SDK.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O programa em si funciona, pois compilei o código fonte sem erros nem warnings. A questão é: embora muito simples e básico, será este um exemplo razoável da citação acima?

Agradecia muito que desses o teu parecer.

Desculpa-me LittleJoe. Vi este post à que tempos, pensei responder mais tarde nesse dia e desde então... nunca mais me lembrei ;)

...

Nope. Não é assim que o fazes :)

Mas a ideia está lá. Vi que sim. O problema, é que para fazeres um wrap à volta de uma API tens que mexer nas próprias declarações da API e não nas definições. O que neste caso, significa alterares windows.h.  Seria aí, onde os vários elementos da API são declarados, que faria sentido  envolver tudo dentro de namespaces. Não que o devas fazer hehe...

O que fizeste no teu código foi criares namespaces à volta de definições e não de declarações.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Muito obrigado Malta.  ;)

Acho melhor seguir o teu conselho Marfig e tirar da cabeça os wraps no windows.h. Estou a ver que nem sabia no que é que me metia.  :shocking:

Já agora, falaram no SDK. Se se estão a referir ao Microsoft DirectX SDK de Agosto de 2007, então já o tenho, mas não consigo encontrar o 'atlbase.h'.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não é o DirectX SDK. Mas sim o Platform SDK.

Thanks Triton.

Já fiz o download do Platform SDK, no entanto quando abro o self-extractor, aparece uma janela a perguntar-me em que directório quero que os ficheiros extraídos sejam postos. O que é certo é que não faço a mais pequena ideia onde pôr os ficheiros extraídos. Poderás dar-me uma ajuda?  :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O meu ficou instalado em C:\Program Files\Platform SDK. Mas isso não será o auto-extract para depois iniciar a instalação propriamente dita?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hmm... pessoal, o Visual Studio 2008 Express Edition já vem com a Platform SDK integrada. Não é nada boa ideia instalar a Platform SDK do 2005 Express Edition.

Se quiseres realmente usar WTL com o 2008 Express vais ter que esperar: http://sourceforge.net/forum/forum.php?thread_id=1880196&forum_id=374433

Mas esperar poderá significar para sempre... Houve algumas alterações de fundo no 2008. Para além do SDK integrado, ao contrário do 2005, o 2008 não vem com ATL. Portanto penso que o projecto WTL levou um tiro de morte.

Entretanto há a considerar o que realmente queres, LittleJoe. Tu queres programar na Windows API, MFC, ou queres simplesmente programar para Windows? Porque se for a última, pessoalmente desaconselho WTL mesmo se conseguires arranjar o 2005 Express (ainda o encontras nos torrents juntamente com o SDK). Aqui a ideia será tirares partido de frameworks que simplifiquem o teu trabalho como o wxWidgets e Qt e te permitem um port relativamente fácil das tuas aplicações para outros sistemas operativos.

Mas se quiseres aprender a usar o core da Microsoft, então mais uma vez WTL não é uma boa ideia, porque te afasta do código MFC/ATL  Assim a ideia neste caso será programares em Windows API e ires juntando um dinheiro e comprares a versão Standard ou Professional do Visual Studio 2008 que já incluem então full MFC/ATL support.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu sei que o Visual Studio 2008 Express já vem com o Win32 SDK, mas não trás tudo o necessário para trabalhar com o WTL. Podes seguir o tutorial do CodeProject e assim já deve funcionar (basicamente é instalar o Platform SDK).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hmm... pessoal, o Visual Studio 2008 Express Edition já vem com a Platform SDK integrada. Não é nada boa ideia instalar a Platform SDK do 2005 Express Edition.

Se quiseres realmente usar WTL com o 2008 Express vais ter que esperar: http://sourceforge.net/forum/forum.php?thread_id=1880196&forum_id=374433

Mas esperar poderá significar para sempre... Houve algumas alterações de fundo no 2008. Para além do SDK integrado, ao contrário do 2005, o 2008 não vem com ATL. Portanto penso que o projecto WTL levou um tiro de morte.

Entretanto há a considerar o que realmente queres, LittleJoe. Tu queres programar na Windows API, MFC, ou queres simplesmente programar para Windows? Porque se for a última, pessoalmente desaconselho WTL mesmo se conseguires arranjar o 2005 Express (ainda o encontras nos torrents juntamente com o SDK). Aqui a ideia será tirares partido de frameworks que simplifiquem o teu trabalho como o wxWidgets e Qt e te permitem um port relativamente fácil das tuas aplicações para outros sistemas operativos.

Mas se quiseres aprender a usar o core da Microsoft, então mais uma vez WTL não é uma boa ideia, porque te afasta do código MFC/ATL  Assim a ideia neste caso será programares em Windows API e ires juntando um dinheiro e comprares a versão Standard ou Professional do Visual Studio 2008 que já incluem então full MFC/ATL support.

Eu sei que o Visual Studio 2008 Express já vem com o Win32 SDK, mas não trás tudo o necessário para trabalhar com o WTL. Podes seguir o tutorial do CodeProject e assim já deve funcionar (basicamente é instalar o Platform SDK).

???  Ei rapaziada, que já estou a ficar confuso!! Não, estou a brincar, sério, obrigado pela ajuda.  :)

Vou fazer outra pergunta. É possível juntar código escrito em Win32 API (C procedimental) e código escrito em C++ (orientado para o objecto) para escrever um programa coerente, sem sacrificar muito a parte orientada para o objecto (não sei se me estão a entender)?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O tutorial no CodeProject é para o 2005 Express..

Volto a insistir. Instalar o platform sdk no visual studio 2008 é muito má ideia. Mas força... ficam avisados.

Vou fazer outra pergunta. É possível juntar código escrito em Win32 API (C procedimental) e código escrito em C++ (orientado para o objecto) para escrever um programa coerente, sem sacrificar muito a parte orientada para o objecto (não sei se me estão a entender)?

Yup. Está sempre acontecer a quem programa para a Win32 API.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se é má ideia, então é o que eu e muitas pessoas que conheço usam para programar. Marfig, já agora, quais são as razões para não funcionar? Corro algum problema a utilizar o Platform SDK no 2008?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se é má ideia, então é o que eu e muitas pessoas que conheço usam para programar. Marfig, já agora, quais são as razões para não funcionar? Corro algum problema a utilizar o Platform SDK no 2008?

Aí está uma pergunta que eu também gostaria de te fazer Marfig. Haverá algum problema em utilizar o SDK no 2008? É que eu já fiz no passado algumas "experiências" das quais me arrependi amargamente.  :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora