Win32窗口包装类 [英] Win32 window wrapper class

查看:54
本文介绍了Win32窗口包装类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好

我在使用c ++的win32包装器类时出现问题

这里是我的代码



Display.h

  #pragma once 
#include < Windows.h >
class 显示
{
private
char * mWindowTitle;
WNDCLASSEX mWndClass;
HWND mHwnd;
MSG mMsg;
int mWidth;
int mHeight;
public
显示( int width, int height, char * windowtitle,WNDPROC messagefunc,HINSTANCE hinst);
~显示( void );
bool InitializeWindow();
HWND GetWindowHandle();
MSG GetMessageHandler();
};





Display.cpp



  #include     display.h 

显示::显示( int width,< span class =code-keyword> int height, char * windowtitle,WNDPROC messagefunc,HINSTANCE hinst)
{
mWindowTitle = windowtitle;
mWidth = width;
mHeight =身高;
mHwnd = 0 ;

// 步骤1注册窗口类
mWndClass。 cbSize = sizeof (WNDCLASSEX); // 结构的大小
mWndClass.style = 0 ; // 类的样式
mWndClass.lpfnWndProc = messagefunc; // 回调函数的函数指针
mWndClass.cbClsExtra = 0 ;
mWndClass.cbWndExtra = 0 ;
mWndClass.hIcon = LoadIcon(hinst,IDI_APPLICATION);
mWndClass.hCursor = LoadCursor(hinst,IDC_ARROW);
mWndClass.hbrBackground =(HBRUSH)(COLOR_WINDOW + 1);
mWndClass.lpszClassName = EngineGameWindow;
mWndClass.lpszMenuName = NULL;
mWndClass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
mWndClass.hInstance = hinst;
}

显示::〜显示(无效
{
}

bool Display :: InitializeWindow()
{
if (! RegisterClassEx(& mWndClass))
MessageBox(NULL, 抱歉无法注册窗口类
窗口注册错误,MB_ICONEXCLAMATION | MB_OK);

// 步骤2创建窗口
mHwnd = CreateWindowEx (WS_EX_CLIENTEDGE, EngineGameWindow,mWindowTitle,
WS_OVERLAPPEDWINDOW,GetSystemMetrics(SM_CXSCREEN)/ 4,
GetSystemMetrics(SM_CYSCREEN)/ 8,
mWidth,mHeight,NULL,NULL,mWndClass.hInstance,NULL);
if (mHwnd == NULL)
MessageBox(mHwnd, 未创建窗口 窗口创建错误 ,MB_ICONEXCLAMATION | MB_OK);

return true ;
}

HWND Display :: GetWindowHandle()
{
return mHwnd;
}

MSG Display :: GetMessageHandler()
{
return mMsg;
}







main.cpp



 LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
if (msg == WM_CHAR&& wparam == VK_ESCAPE)
{
PostQuitMessage( 0 );
return 0 ;
}
switch (msg)
{
case WM_CLOSE: // 何时关闭窗口
// 关闭窗口
DestroyWindow(hwnd);
break ;
case WM_DESTROY: // 当整个窗口类被销毁
//
PostQuitMessage( 0 );
break ;
case WM_PAINT:
ValidateRect(hwnd, 0 );
break ;
默认
return DefWindowProc(hwnd,msg,wparam,lparam);
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}

int WINAPI WinMain(HINSTANCE hinst,HINSTANCE hPrevinstance,LPSTR lpcmdline, int ncmdshow)
{
显示显示=显示( 800 600 Engine,WndProc,hinst);
if (!display.InitializeWindow())
return 0 ;

Directx9Api api = Directx9Api();
if (!api.InitializeApi())
return 0 ;

ShowWindow(display.GetWindowHandle(),SW_SHOW);
UpdateWindow(display.GetWindowHandle());

// 第3步消息循环
while (GetMessage(& display.GetMessageHandler(),display.GetWindowHandle(), 0 0 )> 0
{
TranslateMessage(&(display.GetMessageHandler())) ;
DispatchMessage(&(display.GetMessageHandler()));
}
return 0 ;
}





当我从班级创建窗口时我无法与之交互,即我无法关闭,最小化或最大化它。但是当我在课堂上创建没有它的窗口时,那就是我在主函数中做的所有事情都是这样的。



  int  WINAPI WinMain(HINSTANCE hinst,HINSTANCE hprevinst,LPSTR lpcmdline, int  ncmdshow)
{
WNDCLASSEX wndclassex;
HWND hwnd;
MSG msg;

// 步骤1注册窗口类
wndclassex。 cbSize = sizeof (WNDCLASSEX); // 结构的大小
wndclassex.style = CS_DROPSHADOW; // 班级的风格
wndclassex.lpfnWndProc = WndProc; // 回调函数的函数指针
wndclassex.cbClsExtra = 0 ;
wndclassex.cbWndExtra = 0 ;
wndclassex.hIcon = LoadIcon(hinst,IDI_APPLICATION);
wndclassex.hCursor = LoadCursor(hinst,IDC_ARROW);
wndclassex.hbrBackground =(HBRUSH)(COLOR_WINDOW);
wndclassex.lpszClassName = wndclassname;
wndclassex.lpszMenuName = NULL;
wndclassex.hIconSm = LoadIcon(hinst,IDI_APPLICATION);
wndclassex.hInstance = hinst;

if (!RegisterClassEx(& wndclassex))
{
MessageBox(NULL, 抱歉无法注册窗口类
窗口注册错误,MB_ICONEXCLAMATION | MB_OK);
return 0 ;
}

// 步骤2创建窗口
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,wndclassname, 一个简单的窗口
WS_OVERLAPPEDWINDOW, ((GetSystemMetrics(SM_CXSCREEN)/ 2)/ 2),((GetSystemMetrics(SM_CYSCREEN)/ 2)/ 2), 300 300 ,NULL,NULL,HINST,NULL);

if (hwnd == NULL)
{
MessageBox(hwnd, 抱歉无法创建窗口 窗口创建错误,MB_ICONEXCLAMATION | MB_OK);
return 0 ;
}

ShowWindow(hwnd,ncmdshow);
UpdateWindow(hwnd);

// 第3步消息循环
while (GetMessage(& msg,hwnd, 0 0 )> 0
{
TranslateMessage(& msg);
DispatchMessage(& msg);

}

return msg.wParam;
}





它完美无缺。任何人都可以帮助我



提前致谢。

解决方案

您将在<$ c中返回 MSG 的新副本$ c> GetMessageHandler ,改变它以返回指针,它会起作用。



 MSG * Display :: GetMessageHandler()
{
return & mMsg;
}





然后像这样打电话;

  while (GetMessage(display.GetMessageHandler(),display.GetWindowHandle(), 0  0 >   0 
{
TranslateMessage((display.GetMessageHandler()));
DispatchMessage((display.GetMessageHandler()));
}





希望这会有所帮助,

Fredrik


< blockquote> Fredrik以精确,清晰的方式回应。我将从另一个角度回应。



首先,要回答你的初始问题,考虑写下你的WinMain:



  int  WINAPI WinMain(HINSTANCE hinst,HINSTANCE hPrevinstance,LPSTR lpcmdline, int  ncmdshow)
{
MSG msg = { 0 };
显示显示=显示( 800 600 引擎,WndProc,hinst);
if (!display.InitializeWindow())
return 0 ;

Directx9Api api = Directx9Api();
if (!api.InitializeApi())
return 0 ;

ShowWindow(display.GetWindowHandle(),SW_SHOW);
UpdateWindow(display.GetWindowHandle());

// 第3步消息循环
while (GetMessage(& msg,display.GetWindowHandle(), 0 0 )> 0
{
TranslateMessage(& msg);
DispatchMessage(& msg);
}
return 0 ;
}





您的Display类中的mMsg数据成员引起了我的注意。



  class 显示
{
私人
MSG mMsg;





我想不出存储当前窗口消息的原因这条路。它由窗口过程传递,因此不需要保存它。通过SendMessage递归调用窗口过程并不是闻所未闻的 - 这可能会覆盖mMsg数据成员并导致任何代码混淆,具体取决于它。总之,我建议避免它。



考虑让你的WndProc成为Display类的静态成员。



  class 显示
{
private
static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)





这将使窗口过程可以访问Display的公共和私人成员。



字符串指针mWindowTitle可以变成粘性问题。



  class 显示
{
private
char * mWindowTitle;





考虑将此声明为const - 在构造函数代码注释中提醒一下 - 或者更好 - 制作字符串的副本。使用malloc / free或new / delete或STL std :: string。



最后我要指出的是窗口类。考虑将mWndClass设为静态。如果你的程序只有一个Display类,那么这并不重要。如果您认为您将拥有多个Display实例,请将WNDCLASSEX设置为静态并在所有实例之间共享。



使WNDCLASSEX和WinProc都静态生成一个更简单的构造函数:



  //  注意:调用者必须保证windowtitle的生命周期超过此对象。 
显示::显示( int width, int height, const char * windowtitle)
{
mWindowTitle = windowtitle;
mWidth = width;
mHeight =身高;
mHwnd = 0 ;
}





WNDCLASSEX当然会在别处初始化。



祝你好运!


Hi everyone
I am having a problem with my win32 wrapper class in c++
here is my code

Display.h

#pragma once
#include <Windows.h>
class Display
{
private:
	char* mWindowTitle;
	WNDCLASSEX mWndClass;
	HWND mHwnd;
	MSG mMsg;
	int mWidth;
	int mHeight;
public:
	Display(int width, int height, char* windowtitle, WNDPROC messagefunc, HINSTANCE hinst);
	~Display(void);
	bool InitializeWindow();
	HWND GetWindowHandle();
	MSG GetMessageHandler();
};



Display.cpp

#include "display.h"

Display::Display(int width, int height,char* windowtitle, WNDPROC messagefunc, HINSTANCE hinst)
{
	mWindowTitle = windowtitle;
	mWidth = width;
	mHeight = height;
	mHwnd = 0;

	//Step 1 register the window class
	mWndClass.cbSize = sizeof(WNDCLASSEX); //the size of the structure
	mWndClass.style = 0; //Style of the class
	mWndClass.lpfnWndProc = messagefunc; // function pointer to the callback function
	mWndClass.cbClsExtra = 0;
	mWndClass.cbWndExtra = 0;
	mWndClass.hIcon = LoadIcon(hinst, IDI_APPLICATION);
	mWndClass.hCursor = LoadCursor(hinst,IDC_ARROW);
	mWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	mWndClass.lpszClassName = "EngineGameWindow";
	mWndClass.lpszMenuName = NULL;
	mWndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	mWndClass.hInstance =  hinst;
}

Display::~Display(void)
{
}

bool Display::InitializeWindow()
{
	if(!RegisterClassEx(&mWndClass))
		MessageBox(NULL,"Sorry could not register window class",
						"Window Registration Error", MB_ICONEXCLAMATION | MB_OK);

	//Step 2 creating the window
	mHwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"EngineGameWindow", mWindowTitle,
		WS_OVERLAPPEDWINDOW,GetSystemMetrics(SM_CXSCREEN)/4,
							GetSystemMetrics(SM_CYSCREEN)/8, 
							mWidth, mHeight,NULL,NULL,mWndClass.hInstance,NULL);
	if(mHwnd == NULL)
		MessageBox(mHwnd,"Window not created","Window Creation Error",MB_ICONEXCLAMATION | MB_OK);

	return true;
}

HWND Display::GetWindowHandle()
{
	return mHwnd;
}

MSG Display::GetMessageHandler()
{
	return mMsg;
}




main.cpp

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	if(msg == WM_CHAR && wparam == VK_ESCAPE)
	{
		PostQuitMessage(0);
		return 0;
	}
	switch(msg)
	{
	case WM_CLOSE: //when the window is to be closed
		//close the window 
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY: // When the entire window class is destroyed
		// 
		PostQuitMessage(0);
		break;
	case WM_PAINT:
		ValidateRect(hwnd, 0);
		break;
	default:
		return DefWindowProc(hwnd,msg,wparam,lparam);
	}
	return DefWindowProc(hwnd, msg, wparam, lparam);
}

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
	Display display = Display(800, 600, "Engine",WndProc,hinst);
	if(!display.InitializeWindow())
		return 0;

	Directx9Api api = Directx9Api();
	if(!api.InitializeApi())
		return 0;

	ShowWindow(display.GetWindowHandle(), SW_SHOW);
	UpdateWindow(display.GetWindowHandle());

	//Step 3 the Message loop
	while (GetMessage(&display.GetMessageHandler(),display.GetWindowHandle(),0,0) > 0)
	{
		TranslateMessage(&(display.GetMessageHandler()));
		DispatchMessage(&(display.GetMessageHandler()));
	}
	return 0;
}



When i create a window from the class i cant interact with it that is, i cant close, minimize or maximize it. But when i create the window without it in a class, that is when i do everything in the main function like this

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst,LPSTR lpcmdline, int ncmdshow)
{
	WNDCLASSEX wndclassex;
	HWND hwnd;
	MSG msg;

	//Step 1 register the window class
	wndclassex.cbSize = sizeof(WNDCLASSEX); //the size of the structure
	wndclassex.style = CS_DROPSHADOW; //Style of the class
	wndclassex.lpfnWndProc = WndProc; // function pointer to the callback function
	wndclassex.cbClsExtra = 0;
	wndclassex.cbWndExtra = 0;
	wndclassex.hIcon = LoadIcon(hinst, IDI_APPLICATION);
	wndclassex.hCursor = LoadCursor(hinst,IDC_ARROW);
	wndclassex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
	wndclassex.lpszClassName = wndclassname;
	wndclassex.lpszMenuName = NULL;
	wndclassex.hIconSm = LoadIcon(hinst, IDI_APPLICATION);
	wndclassex.hInstance =  hinst;

	if(!RegisterClassEx(&wndclassex))
	{
		MessageBox(NULL, "Sorry could not register window class",
			"Window Registration Error", MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	//Step 2 creating the window
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,wndclassname,"A simple window",
		WS_OVERLAPPEDWINDOW,((GetSystemMetrics(SM_CXSCREEN)/2)/2), ((GetSystemMetrics(SM_CYSCREEN)/2)/2), 300, 300,NULL,NULL,hinst,NULL);
	
	if(hwnd == NULL)
	{
		MessageBox(hwnd,"Sorry could not create a window","Window Creation Error",MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, ncmdshow);
	UpdateWindow(hwnd);

	//Step 3 the Message loop
	while (GetMessage(&msg,hwnd,0,0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);

	}

	return msg.wParam;
}



it works perfectly.Can anyone help me

Thanks in advance.

解决方案

You're returning a new copy of your MSG in GetMessageHandler, change that to return a pointer instead, and it will work.

MSG* Display::GetMessageHandler()
{
    return &mMsg;
}



And then call it like this;

while (GetMessage(display.GetMessageHandler(), display.GetWindowHandle(), 0, 0) > 0)
{
    TranslateMessage((display.GetMessageHandler()));
    DispatchMessage((display.GetMessageHandler()));
}



Hope this helps,
Fredrik


Fredrik has responded in a precise, clear way. I'm going to respond from a different angle.

First, to answer your initial question, consider writing your WinMain like this:

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
        MSG msg = {0};
	Display display = Display(800, 600, "Engine",WndProc,hinst);
	if(!display.InitializeWindow())
		return 0;
 
	Directx9Api api = Directx9Api();
	if(!api.InitializeApi())
		return 0;
 
	ShowWindow(display.GetWindowHandle(), SW_SHOW);
	UpdateWindow(display.GetWindowHandle());
 
	//Step 3 the Message loop
	while ( GetMessage(&msg, display.GetWindowHandle(), 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}



The "mMsg" data member in your Display class caught my attention.

class Display
{
private:
	MSG mMsg;



I could not think of a reason for storing the current window message this way. It's passed around by the window procedure so there's no need to save it. It is not unheard of for the window procedure to be called recursively via SendMessage - which might overwrite the mMsg data member and cause confusion for any code depending on it. In short, I suggest avoiding it.

Consider making your WndProc a static member of the Display class.

class Display
{
private:
    static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)



This will give the window procedure access to public and private members of Display.

The string pointer "mWindowTitle" can become a sticky issue.

class Display
{
private:
	char* mWindowTitle;



Consider declaring this as const - with a word of caution in the constructor code comments - or perhaps better - make a copy of the string. Use malloc / free or new / delete or an STL std::string.

Last thing I want to point out is the window class. Consider making "mWndClass" static. If your program will only ever have one Display class, then this doesn't matter so much. If you think you'll have more than one Display instance, make the WNDCLASSEX static and shared across all instances.

Making WNDCLASSEX and WinProc both static yields a simpler constructor:

// Caution: caller must guarantee lifetime of windowtitle exceeds this object.
Display::Display(int width, int height, const char* windowtitle)
{
	mWindowTitle = windowtitle;
	mWidth = width;
	mHeight = height;
	mHwnd = 0;
}



The WNDCLASSEX would of course be initialized elsewhere.

Good luck!


这篇关于Win32窗口包装类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆