Aregisterclass怎么用啊, 比如WNDCLASS wndclass; 在注册时是 registerclass(&wndclass)?

2024-05-08 15:49

1. Aregisterclass怎么用啊, 比如WNDCLASS wndclass; 在注册时是 registerclass(&wndclass)?

就调用RegisterClass,API头文件会根据你的项目是否定义了UNICODE宏而决定将RegisterClass定义为RegisterClassW或RegisterClassA,实际上绝大多数WindowsAPI函数都是这样做的。比如winuser.h文件中有这样的代码:
 
#ifdef UNICODE
#define RegisterClass  RegisterClassW
#else
#define RegisterClass  RegisterClassA
#endif // !UNICODE

Aregisterclass怎么用啊, 比如WNDCLASS wndclass; 在注册时是 registerclass(&wndclass)?

2. wndclass的创建问题

  你好,先用RegisterClass注册一个窗口类,这个窗口类型是你在createwindow中的第一个参数的值。然后用createwindow创建该窗口类的窗口实例。MsgProc(HWND hwnd,UINT msg,WPARRAM wParam,LPARAm IParam)这个函数是窗口的消息处理函数,在注册窗口类的时候指定的。该函数可以在默认窗口函数的基础上实现你自己的窗口消息处理。
  也不难理解的,关键是动手做一下熟悉一下这个过程就好了。祝你好运!

3. win32编程 为什么要注册窗口类?注册窗口类究竟做了哪些工作?

你想创建什么样的窗口呢?那么,创建什么样的窗口呢?创建前,Window系统可不知道你要的是什么类型的窗口啊(比如标题栏上显示什么图标,鼠标形状是什么,窗口背景颜色等等)。这些类型信息应在你创建前事先告诉Window系统。可以采用这种方法:就是我们事先写一份要创建窗口的类型申请表,提交(注册)给Window系统。然后在创建时,可以让Windows按这个申请表来创建你所要的窗口了。也就是说我们还应该先提交一个申请表,申请成功后再根据这个表创建一个窗口。

我们在使用microsoft平台SDK或者MFC编程时,在创建窗口类后都要先用RegisterClass函数来注册窗口类,这个函数需要一个指向窗口类结构的指针。那么RegisterClass这个windows API函数到底做了什么呢,关于这个函数的源码微软是不会给出来的,因为它只是提供一个系统编程接口,网上也找不到相关说明,只是粗略介绍需要将类注册给系统,但从msdn的atom table说明中我们发现这样一段说明。

The system uses atom tables that are not directly accessible to applications. However, the application uses these atoms when calling a variety of functions. For example, registered clipboard formats are stored in an internal atom table used by the system. An application adds atoms to this atom table using。

答案有了,在我们构造一个窗口类结构后,我们需要将这个类结构指针加入到system atom table 即SAT中,这样系统就可以通过查找这张表来找到用户自定义的窗口类,window预定义的窗口类指针也在SAT中。SAT实际上实现了一种用于查询的映射,atom实际类型是short,即16位数据。只有系统才可直接访问这张表,但在调用某些api函数时,如Registerclass,可以告知系统来存取这张表。当然,还有本地原子表和全局原子表,这些表应用程序是可以直接访问的。

win32编程 为什么要注册窗口类?注册窗口类究竟做了哪些工作?

4. 要用MFC创建一个窗口,如何创建?

创建一个完整窗口要经历的步骤:
1)设计一个窗口类;
2)注册窗口类;
3)创建窗口;
4)显示及更新窗口。

第一步:
windows 已经为用户定义了一个完整的窗口类,用户只需要将各个属性填满既可以。窗口类是一个 结构体,其定义如下:
typedef struct _WNDCLASS{
   UINT style;//class style
   WNDPROC lpfnWndProc;
   int cbClsExtra;
   int cbWndExtra;
   HANDLE hInstance;
   HICON    hIcon;
   HCURSOR hCursor;
   HBRUSH   hbrBackground;
   LPCTSTR lpszMenuName;
   LPCTSTR lpszClassName;
}WNDCLASS;
第二步:
用RegisterClass(&wndclass)来定义的窗口注册。
第三步:创建窗口
1)定义一个句柄,然后用CreateWindow()来为句柄赋值。函数用法参看MSDN。创建窗口必须依据已经声明并且已经注册的窗口类型来创建。
HWND CreateWindow(
   LPCTSTR    lpClassName,//定义的窗口类名
   LPCTSTR    lpWindowName,//窗口的名字,将会在标题栏上显示出来的
   DWORD      dwStyle,//窗口的风格(窗口的外观模式和功能按钮等等)
   int        x,//窗口初始位置ws_usedefault
   int        y,//同上
   int        nWidth,//窗口的宽度,可以用ws_usedefault
   int        nHeight,//窗口高度,可以用ws_usedefault
   HWND       hWndParent,//父窗口的句柄,单一窗口则设置为空
   HMENU      hMenu,//菜单的句柄,如果没有菜单则将这个句柄设置为空
   HINSTANCE hInstance,//由系统进行分配标识
   LPVOID     lpParam//一般设置为空
);
第四步:显示窗口
调用ShowWindow()函数来显示窗口。
ShowWindow(
HWND   hWnd,//要显示的窗口的句柄
int    nCmdShow//显示窗口的模式,如:最大化最小花显示
)
第五步:更新窗口
在显示窗口的函数调用完毕以后调用UpdateWindow()来对窗体进行更新
UpdateWindow(hwnd);//这个函数没有并不影响消息产生。
//消息循环
MSG msg;//定义了一个消息结构体变量
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} 
/*
GetMessage( 
LPMSG lpMsg,
//消息结构提的指针,无需对这个消息结构提的内部成员初始化,
//这个只需将定义的结构体的地址传到这里
HWND hWnd,
//窗口句柄,指明要获得的是那个窗口的消息,如果要获取所有窗口的消息则
//定义为NULL
UINT wMsgFilterMin,
//用来指定要从消息队列里边取得的最小值,
UINT wMsgFilterMax
//用来指定要从消息队列里边取得的最大值,
///////////////////////////////////////////////////////////////////////
//这两个参数用来限制GETMESSAGE 在消息队列里边的取值范围,//
//以去处调一些确定不感兴趣的消息                                 //
//if要从消息队列中所有的消息中提取的话则两个参数均设定为 //
//零                                                                                  // 
/////////////////////////////////////////////////////////////////////// 
);//从调用程序线程消息队列中取消息
*/
有了创建窗口的整个流程以后,现在就开始定义窗口过程,用WindowProc()
LRESULT CALLBACK WindowProc(/*函数名字可以更改,但是参数不允许改变*/
           HWND    hwnd,
           UINT    uMsg,
           WPARAM wParam,
           LPARAM lParam
);//参数和消息结构提的前四个参数相同,事实上系统在调用窗口过程函数
//的时候自动将消息结构体的前四个参数传递到窗口过程

5. c++编程的窗口没有没有显示

我帮你调试了下,这个程序问题很多,从RegisterClass(&wndclass);//注册窗口类之前就有问题,句柄无效。 所以RegisterClass(&wndclass);和CreateWindow全部调用失败了。你可以看看hWnd的值,返回的是0. 窗口就没创建,不显示很正常。 WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX);  wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DFH); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_DFH; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); 上面是MFC自动生成的创建窗口类的代码,用的是RegisterClassEx(&wcex);注册的。 仔细看看吧,或许你有新的发现!

c++编程的窗口没有没有显示

6. 学习MFC框架如何创建的过程

CChildFrame做为子窗口包含于MDIClient中(可以包含多个),CChildFrame里面则是真实的文档表示窗口CMDITestView了。 我们从这里开始:// CMDITestApp 初始化BOOL CMDITestApp::InitInstance() 做为CWinApp的派生类,通常需要重载InitInstance(), ExitInstance()两个函数,以完成应用的初始化和退出。我们现在关心InitInstance中关于文档模板、窗口处理的部分,而忽略掉一些CommonControl, OLE初始化部分。 整个InitInstance代码如下:BOOL CMDITestApp::InitInstance(){ InitCommonControls(); // 这里删减了大量注释和错误处理 CWinApp::InitInstance(); AfxOleInit(); AfxEnableControlContainer(); SetRegistryKey(_T(“应用程序向导生成的本地应用程序“)); LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) TRACE(“Before CMultiDocTemplate\n“); // 注册应用程序的文档模板。文档模板 // 将用作文档、框架窗口和视图之间的连接 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView)); if (!pDocTemplate) return FALSE; TRACE(“Before AddDocTemplate\n“); AddDocTemplate(pDocTemplate); // 创建主 MDI 框架窗口 TRACE(“Before new CMainFrame\n“); CMainFrame* pMainFrame = new CMainFrame; TRACE(“Before pMainFrame->LoadFrame\n“); if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; TRACE(“Before ParseCommandLine\n“); CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 调度在命令行中指定的命令。如果 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 TRACE(“Before ProcessShellCommand\n“); if (!ProcessShellCommand(cmdInfo)) return FALSE; TRACE(“Before pMainFrame->ShowWindow\n“); // 主窗口已初始化,因此显示它并对其进行更新 pMainFrame->ShowWindow(m_nCmdShow); TRACE(“Before pMainFrame->UpdateWindow\n“); pMainFrame->UpdateWindow(); return TRUE;} 为了研究整个创建过程,我在其中添加了一些TRACE来跟踪创建顺序。 忽略掉开始的乱七八糟的初始化,从CMultiDocTemplate开始: CMultiDocTemplate* pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView)); AddDocTemplate(pDocTemplate);(作了一点点简化)这里首先创建了一个CMultiDocTemplate ——文档模板,文档模板包括的三个运行时刻类信息:Document – CMDITestDoc, FrameWnd – CChildFrame, View – CMDITestView。然后通AddDocTemplate函数将新创建的文档模板添加到模板管理器之中(我们以后再研究模板管理器)。 然后创建主框架窗口CMainFrame: CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; 其中,需要研究的是LoadFrame的实现,以及里面都做了些什么。我们稍后研究。 处理命令行,在这里第一个空文档被建立出来: CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // 调度在命令行中指定的命令。如果用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 if (!ProcessShellCommand(cmdInfo)) // �0�8 这里创建出初始空文档 return FALSE; 我们一会会重点研究ProcessShellCommand。 最后,显示主窗口: pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); 至此,WinApp::InitInstance()完成了自己的工作。 上面遗留了三个待研究的分支,让我们现在去研究它们:1、 CDocTemplate2、 CFrameWnd::LoadFrame3、 CWnd::ProcessShellCommand 研究CDocTemplate 我们的例子中是构造了一个CMultiDocTemplate,它是从CDocTemplate派生而来,所以我们主要研究CDocTemplate。CDocTemplate的几个关键属性列表如下: CRuntimeClass* m_pDocClass; // class for creating new documents CRuntimeClass* m_pFrameClass; // class for creating new frames CRuntimeClass* m_pViewClass; // class for creating new views 其中:m_pDocClass表示文档类类型,在此例子中就是CMDITestDocm_pFrameClass表示容纳View窗口的框架窗口类类型,此例中为CChildFramem_pViewClass表示显示文档的View视类类型,此例中为CMDITestView 我们可以这样认为,CDocTemplate用于描述Frame-View-Doc的关系。当然它还有一大堆别的属性,我们暂时先忽略。 一会还会看到CDocTemplate的创建文档、框架、视的过程,OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) // 关键是这里 OnFileNew(); if (m_pMainWnd == NULL) bResult = FALSE; break; case CCommandLineInfo::FileOpen: // 忽略 case CCommandLineInfo::FilePrintTo: // 忽略 case CCommandLineInfo::FilePrint: case CCommandLineInfo::FileDDE: case CCommandLineInfo::AppRegister: case CCommandLineInfo::AppUnregister: } return bResult;}进入到ProcessShellCommand,要处理很多种不同命令,我们忽略其它命令,单独看FileNew部分。注意:实际进入到了AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)之中。 AfxGetApp()实际返回了CMDITestApp的唯一实例,它从CWinApp – CWinThread – CCmdTarget – CObject 派生而来。我们没有重载OnCmdMsg,所以进入到CCmdTarget的OnCmdMsg处理中。为了研究,我们删减了一些代码。BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo){ // 这里删减了一些代码 // determine the message number and code (packed into nCode) const AFX_MSGMAP* pMessageMap; const AFX_MSGMAP_ENTRY* lpEntry; UINT nMsg = 0; // 这里删减了一些代码,处理后 nMsg = WM_COMMAND // 为了简化,删减了一些断言等。以下循环用于查找处理此消息的入口。

7. mfc窗口注册、创建

首先从CXXXApp::InitInstance调用LoadFrame
BOOL CMyApp::InitInstance(){    // ......        // 创建主 MDI 框架窗口    CMainFrame* pMainFrame = new CMainFrame;    if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))        return FALSE;            // ......        CCommandLineInfo cmdInfo;    ParseCommandLine(cmdInfo);    // 调度在命令行中指定的命令。如果    // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。    if (!ProcessShellCommand(cmdInfo)) return FALSE;}LoadFrame是虚函数,没有被重写,所以调用CMDIFrameWnd::LoadFrame
BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,    CWnd* pParentWnd, CCreateContext* pContext){    if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle,      pParentWnd, pContext))        return FALSE;继续调用CFrameWnd::LoadFrame
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,    CWnd* pParentWnd, CCreateContext* pContext){    //。。。    VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));    // 。。。    if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,      pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))    {这里能看到 AfxDeferRegisterClass 和 Create
这里的Create调用了CFrameWnd::Create,其他的Create还有CMDIChildWnd和CWnd的
里面调用到CreateEx,CreateEx几乎没有被重写,调用的是CWnd::CreateEx
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,    LPCTSTR lpszWindowName, DWORD dwStyle,    int x, int y, int nWidth, int nHeight,    HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){    //。。。        if (!PreCreateWindow(cs))    {        PostNcDestroy();        return FALSE;    }    AfxHookWindowCreate(this);    HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,            cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,            cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);接着调用PreCreateWindow后就是用CreateWindowEx创建窗口
BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs){    if (cs.lpszClass == NULL)    {        VERIFY(AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG));        cs.lpszClass = _afxWndMDIFrame;    }    return TRUE;}这里也有个AfxDeferRegisterClass,它被宏替换后是AfxEndDeferRegisterClass,里面就是注册窗口类的代码
其他类型的窗口也类似,就算LoadFrame没有的话,PreCreateWindow也会调用注册


另外如果是单文档的话,没有主框架,靠的是InitInstance里的ProcessShellCommand
cmdInfo构造时默认是FileNew
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo){    BOOL bResult = TRUE;    switch (rCmdInfo.m_nShellCommand)    {    case CCommandLineInfo::FileNew:        if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))            OnFileNew();这里发送ID_FILE_NEW,就算失败也手动调用OnFileNew
之后就也是创建窗口

建议你装vs2003或以后版本,用 转到定义 检查代码就很容易看到了,vc6之前的版本可能有时不太好用
另外对于MFC建议你弄本《深入浅出MFC》看看

mfc窗口注册、创建

8. C++中怎么用API创建窗口???急急急急急急!!!

新建一个32空程序,在里面新建一个.cpp文件。然后把下面的代码考进去,运行就会起来一个窗口。你仔细看看这个吧,我自己写了,有注释。
/////////////////////////////////////////////////////////win.cpp///////////////////////////////////////////////////////////////////
#include 
#include "stdio.h"
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
//消息处理函数原形
bool g_btxt = false;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	char *szClassName = "WndClass";
	WNDCLASSEX wndclass;									//用描述主窗口的参数填充WNDCLASSEX 结构
	wndclass.cbSize = sizeof(wndclass);						//定义结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	//定义窗口样式
	wndclass.lpfnWndProc = WndProc;							//指定本窗口的消息处理函数
	wndclass.cbClsExtra = 0;								//没有额外的类内存
	wndclass.cbWndExtra = 0;								//没有额外的窗口内存
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);		//使用默认的图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);			//使用默认的光标
	wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);	//定义窗口的背景颜色为灰色
	wndclass.hInstance = hInstance;							//实例句柄
	wndclass.lpszClassName = szClassName;					//窗口类名称
	wndclass.lpszMenuName = NULL;							//不使用菜单
	wndclass.hIconSm = NULL;								//没有类的小图标
	//注册窗口类
	::RegisterClassEx(&wndclass);
	//创建主窗口
	HWND hwnd = ::CreateWindowEx(0,		 //不定义扩展样式
		szClassName,					 //类名
		"Hello world",					 //窗口标题
		WS_OVERLAPPEDWINDOW,			 //窗口风格
		CW_USEDEFAULT,					 //默认的窗口X 轴坐标
		CW_USEDEFAULT,					 //默认的窗口Y 轴坐标
		CW_USEDEFAULT,					 //默认的窗口宽度
		CW_USEDEFAULT,					 //默认的窗口高度
		NULL,							 //没有父窗口句柄
		NULL,							 //没有菜单句柄
		hInstance,						 //程序实例句柄
		NULL);							 //没有用户数据
	if(hwnd == NULL)
	{
		::MessageBox(NULL,"创建窗口出错","error",MB_ICONHAND);
		return -1;
	}
										 
	::ShowWindow(hwnd,nCmdShow);		 //显示窗口										 
	::UpdateWindow(hwnd);				 //刷新窗口客户区
	MSG msg;
	while(::GetMessage(&msg,NULL,0,0))   //从消息队列中取出消息,交给消息处理函数处理,直到GetMessage 函数返回FALSE ,结束消息循环
	{
										 
		::TranslateMessage(&msg);		 //转化键盘消息
										 
		::DispatchMessage(&msg);		 //将消息发送给消息处理函数
	}
	return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	char *szText = "My first window process ";
	HDC hdc;											//声明设备环境句柄
	PAINTSTRUCT ps;
	switch(msg)
	{
	case WM_PAINT:										//窗口客户区需要重画
		{
		
			if (g_btxt == false)
			{
				hdc = ::BeginPaint(hwnd,&ps);				//使无效的客户区变得有效,并取得设备环境句柄
				::TextOut(hdc,0,0,szText,strlen(szText));
				::EndPaint(hwnd,&ps);
				g_btxt = true;
			}
			return 0;
		}
	case WM_DESTROY:									//正在销毁窗口
		{
														
			::PostQuitMessage(0);						//向消息队列投递一个WM_QUIT 消息,促使GetMessage 函数返回0,结束消息循环
			return 0;
		}
	case WM_KEYDOWN:
		switch (wParam)
		{
		case VK_ESCAPE:
			PostMessage(hwnd, WM_QUIT, 0, 0);
			break;
		}
		break;
	case WM_LBUTTONDOWN:
		UINT x, y;
		LPSTR info = new char[50];
		x = LOWORD(lParam);
		y = HIWORD(lParam);
		sprintf(info, "%d_%d", x, y);
		MessageBox(hwnd, info, "mouse info", MB_OK);
		delete info;
		break;
	}													
	return ::DefWindowProc(hwnd,msg,wParam,lParam);		// 将我们不处理的消息交给系统做默认处理
}
///////////////////////////////////////////////////////////////////////////////
运行后效果: