【win32】day03-窗口注册和创建

Win32窗口程序创建步骤  

  1.1 WinMain入口函数的定义

  1.2 WindowProc函数的定义

  1.3 注册窗口类

      RegisterClass/RegisterClassEx

  1.4 创建窗口

      CreateWindow/CreateWindowEx

  1.5 窗口的显示和刷新

      ShowWindow/UpdateWindow

  1.6 消息处理

      GetMessage/DispatchMessage

  1.7 窗口退出

      WM_DESTROY/PostQuitMessage

窗口的注册

2.1 窗口类的分类

  2.1.1 系统全局的窗口类.比如按钮("BUTTON")、文本编辑框("EDIT")等。

  2.1.2 应用程序的全局窗口类。可以在一个应用程序中EXEDLL等所有模块中使用的窗口类。

  2.1.3 局部窗口类。只能在本模块中使用的窗口类。

 

2.2 实现窗口类的注册

  2.2.1 系统全局的窗口类,无需注册直接使用。

使用CreateWindow函数,在CLASSNAME中指定系统已经定义好的窗口类型名称即可。

  2.2.2 应用程序的全局窗口类,需要用代码实现注册,在注册时需要增加CS_GLOBALCLASS定义。

实现方式:

   WNDCLASS wc = {0};

   wc.style = CS_GLOBALCLASS|CS_HREDRAW..;

   ....

   RegisterClass( &wc );

   

  2.2.3 局部窗口类,不是增加CS_GLOBALCLASS定义。

使用RegisterClassRegisterClassEx注册

typedef struct _WNDCLASSEX {

UINT    cbSize; //结构体的大小

  UINT    style;

  WNDPROC lpfnWndProc;

  int     cbClsExtra;

  int     cbWndExtra;

  HANDLE  hInstance;

  HICON   hIcon;

  HCURSOR hCursor;

  HBRUSH  hbrBackground;

  LPCTSTR lpszMenuName;

  LPCTSTR lpszClassName;

  HICON   hIconSm; //小图标

} WNDCLASSEX;

2.2.4 窗口类风格,针对WNDCLASSEX结构体中的style成员的说明。

   CS_HREDRAW 窗口水平变化,重新绘制窗口。

   CS_VREDRAW 窗口垂直变化,重新绘制窗口。

   CS_DBCLICK 窗口可以接收鼠标双击消息

   CS_GLOBALCLASS 创建应用程序全局窗口类。

   CS_BYTEALIGNWINDOW 窗口对齐方式,8的倍数对齐

   CS_BYTEALIGNCLIENT 窗口客户区对齐方式,8的倍数对齐

   CS_CLASSDC 所有这种类型的窗口使用同一个DC(设备描述表,绘图使用)

   CS_OWNDC 每个窗口拥有自己的DC

   CS_PARENTDC 使用父窗口的DC

   CS_SAVEBITS 是用位图保存窗口界面,可以提高窗口界面的刷新性能

   CS_NOCLOSE 禁止关闭命令.

2.2.5 窗口类的附加数据 针对WNDCLASSEX结构体中的cbClsExtra成员的说明。

  在窗口类的数据信息中添加自己信息.

   cbClsExtra 用于添加信息的内存的大小

   SetClassLong 将信息保存到内存中

   GetClassLong 将信息从内存中取出

 DWORD SetClassLong(

  HWND hWnd,//窗口的句柄

  int nIndex, //值的索引号

  LONG dwNewLong   //

);

 DWORD GetClassLong(

  HWND hWnd,//窗口的句柄

  int nIndex, //值的索引号

);

cbClsExtra的长度一般是4字节的倍数

2.2.6 窗口附加数据 针对WNDCLASSEX结构体中的cbWndExtra成员的说明。

   在窗口的数据信息中添加自己信息.

cbWndExtra 用于添加信息的内存的大小

SetWindowLong 将信息保存到内存中

GetWindowLong 将信息从内存中取出

2.3 窗口类的相关函数

  RegisterClass/RegisterClassEx 注册

  UnregisterClass 注销

  GetClassInfo/GetClassInfoEx 获取信息

  GetClassName 获取窗口的窗口类名称

  GetClassLong/SetClassLong 窗口类附加数据的设置和获取

  GetWindowLong/SetWindowLong 窗口的附加数据的设置和获取

 

2.4 创建窗口时如何定位窗口类

  2.4.1 查找应用程序局部的窗口类。如果找到,执行2.4.2,否则执行2.4.3

  2.4.2 如果找到名称一致的窗口类,会比较HISNTANCE句柄。如果相等,就使用找到的窗口类信息创建窗口,如果不同,继续查找,执行2.4.3

  2.4.3 如果未找到名称一致的窗口类,会继续在应用程序全局窗口类中查找。如果找到,执行2.4.4,否则执行2.4.5

  2.4.4 全局窗口类找到一致的,使用找到的窗口类信息创建窗口。

  2.4.5 系统全局窗口类中查找。如果找到,创建窗口,否则返回失败。

总结:先局部,后应用程序全局,再系统全局。

#include <windows.h>
#include "stdio.h"

HINSTANCE g_hInst = NULL;

LRESULT CALLBACK WndProc( HWND hWnd,
						  UINT nMsg,
						  WPARAM wParam,
						  LPARAM lParam )
{
	switch( nMsg )
	{
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	}
	return DefWindowProc( hWnd, nMsg,
		wParam, lParam );
}

HWND CreateButton( )
{
	HWND hWnd = CreateWindow(
		"BUTTON", "Button",
		WS_OVERLAPPEDWINDOW, 0, 0, 500, 600,
		NULL, NULL, g_hInst, NULL );
	return hWnd;
}

void DisplayWnd( HWND hWnd )
{
	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );
}

void Message( )
{
	MSG msg = { 0 };
	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}
}

BOOL RegisterWnd( LPSTR pszClassName )
{
	WNDCLASSEX wce = {0};
	wce.cbSize      = sizeof( wce );
	wce.style       = CS_VREDRAW|CS_HREDRAW;
	wce.lpfnWndProc = WndProc;
	wce.cbClsExtra  = 100;
	wce.cbWndExtra  = 100;
	wce.hCursor     = NULL;
	wce.hIcon       = NULL;
	wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
	wce.lpszClassName = pszClassName;
	wce.hIconSm       = NULL;
	wce.hInstance     = g_hInst;
	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 == nAtom )
	{
		return FALSE;
	}
	return TRUE;
}

HWND CreateWnd( LPSTR pszClassName )
{
	HWND hWnd = CreateWindow( pszClassName,
		"MyWnd", WS_OVERLAPPEDWINDOW,
		0, 0, 400, 500, NULL, NULL, g_hInst,
		NULL );
	return hWnd;
}

void SetExtra( HWND hWnd )
{	//设置CLASS附加数据
	SetClassLong( hWnd, 1, 100 );
	//设置Window附加数据
	SetWindowLong( hWnd, 1, 200 );
}

void GetExtra( HWND hWnd )
{	//获取CLASS附加数据
	DWORD nClass = GetClassLong( hWnd, 1 );
	//获取Window附加数据
	DWORD nWnd  = GetWindowLong( hWnd, 1 );
	//显示
	CHAR szText[260] = { 0 };
	sprintf( szText, "CLS:%d WND:%d", 
		nClass, nWnd );
	MessageBox( NULL, szText, "Extra",
		MB_OK );
}

int WINAPI WinMain( HINSTANCE hInst,
				    HINSTANCE hPrevInst,
					LPSTR pszCmdLine,
					int nShowCmd )
{
	g_hInst = hInst;
	
	//HWND hWndBtn = CreateButton( );
	//DisplayWnd( hWndBtn );

	RegisterWnd( "MyWnd1" );
	HWND hMyWnd1 = CreateWnd( "MyWnd1" );
	HWND hMyWnd2 = CreateWnd( "MyWnd1" );
	SetExtra( hMyWnd1 );
	GetExtra( hMyWnd1 );
	GetExtra( hMyWnd2 );
	
	DisplayWnd( hMyWnd1 );
	Message( );
	return 0;
}

窗口创建

3.1 窗口创建函数

 CreateWindow/CreateWindowEx

  HWND CreateWindowEx(

  DWORD dwExStyle,//窗口的扩展样式

  LPCTSTR lpClassName,  // pointer to registered class name

  LPCTSTR lpWindowName, // pointer to window name

  DWORD dwStyle,        // window style

  int x,                // horizontal position of window

  int y,                // vertical position of window

  int nWidth,           // window width

  int nHeight,          // window height

  HWND hWndParent,      // handle to parent or owner window

  HMENU hMenu,          // handle to menu, or child-window identifier

  HINSTANCE hInstance,  // handle to application instance

  LPVOID lpParam );     // pointer to window-creation data

 3.2 窗口风格和扩展风格

窗口风格: WS_XXXX定义的风格,是窗口的基本风格.

扩展风格: WS_EX_XXXXX 定义的风格,是窗口的扩展风格.比如: ToolWindow窗口等等.

CreateWindow可以使用基本窗口风格,扩展的窗口风格,需要使用CreateWindowEx设置.

WS_OVERLAPPED窗口,层叠式窗口

WS_POPUP窗口,弹出式窗口

WS_CHILD窗口,子窗口

 3.3 父窗口和子窗口

3.3.1 CreateWindow,指定父窗口

3.3.2 将窗口的风格增加WS_CHILD

3.3.3 可以使用SetParentGetParent函数设置和获取指定窗口的父窗口.

其他: MoveWindow 移动窗口.

// WinCreate.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

HINSTANCE g_hInst = NULL;
// 父窗口的处理函数
LRESULT CALLBACK WndProc( HWND hWnd,
						  UINT nMsg,
						  WPARAM wParam,
						  LPARAM lParam )
{
	switch( nMsg )
	{
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	}
	return DefWindowProc( hWnd, nMsg, 
		wParam, lParam );
}
//子窗口的处理函数
LRESULT CALLBACK ChildProc( HWND hWnd,
						    UINT nMsg,
							WPARAM wParam,
							LPARAM lParam )
{
	return DefWindowProc( hWnd, nMsg, 
		wParam, lParam );
}
//消息处理函数
void Message( )
{
	MSG msg = { 0 };
	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		DispatchMessage( &msg );
	}
}
//显示窗口
void DisplayWnd( HWND hWnd )
{
	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );
}
//创建窗口
HWND CreateWnd( LPSTR pszClassName, 
			    DWORD nStyle,
			    HWND  hParent )
{
	HWND hWnd = CreateWindowEx( 
		0,
		pszClassName, 
		"MyWnd", 
		nStyle,
		CW_USEDEFAULT, 
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		hParent,NULL,g_hInst,NULL );
	return hWnd;
}
//注册窗口
BOOL RegisterWnd( LPSTR	  pszClassName, 
				  WNDPROC proc,
				  int     nBrush )
{
	WNDCLASSEX wce = { 0 };
	wce.cbSize      = sizeof( wce );
	wce.style       = CS_HREDRAW|CS_VREDRAW;
	wce.cbClsExtra  = 0;
	wce.cbWndExtra  = 0;
	wce.lpfnWndProc = proc;
	wce.hIcon		= NULL;
	wce.hCursor     = NULL;
	wce.hbrBackground = HBRUSH( nBrush );
	wce.hInstance     = g_hInst;
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.hIconSm       = NULL;
	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 == nAtom )
	{
		return FALSE;
	}
	return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	g_hInst = hInstance;
	//注册父窗口类
	RegisterWnd( "MyWnd", WndProc, 
		COLOR_BTNFACE+1 );
	//注册子窗口类
	RegisterWnd( "Child", ChildProc,
		COLOR_WINDOW );
	//创建父窗口
	HWND hWnd = CreateWnd( "MyWnd", 
		WS_OVERLAPPEDWINDOW, NULL );
	//创建子窗口
	HWND hChild1 = CreateWnd( "Child", 
		WS_CHILD|WS_VISIBLE|WS_BORDER|
		WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|
		WS_MINIMIZEBOX|WS_MAXIMIZEBOX, 
		hWnd );
	HWND hChild2 = CreateWnd( "Child", 
		WS_POPUP|WS_VISIBLE|
		WS_THICKFRAME|WS_CAPTION|WS_SYSMENU, 
		hWnd );
	HWND hChild3 = CreateWnd( "Child", 
		WS_CHILD|WS_VISIBLE|WS_BORDER, 
		hWnd );
	//移动窗口位置
	MoveWindow( hChild1, 100, 100, 
		200, 200, TRUE );
	MoveWindow( hChild2, 100, 200, 
		200, 200, TRUE );
	MoveWindow( hChild3, 100, 300, 
		200, 200, TRUE );
	//显示父窗口
	DisplayWnd( hWnd );
	Message( );
	return 0;
}

3.4 MDI窗口的创建

3.4.1 创建主窗口

   注册主窗口类型,创建主窗口.

HWND hWnd = CreateWindowEx( 0,

pszClassName, "MainWnd",

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, NULL, NULL, g_hInst,

NULL );

3.4.2 创建MDICLIENT窗口

1 添加CLIENTCREATESTRUCT结构,作为附加数据

CLIENTCREATESTRUCT cs = { 0 };

cs.idFirstChild = 1000;//MDI第一个子窗口的ID

2 创建时,使用"MDICLIENT"窗口类型.

3 它的父窗口是主窗口

HWND hWnd = CreateWindowEx( 0,

"MDICLIENT", "MainWnd",

WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, hParent, NULL, g_hInst,

&cs );

3.4.3 创建一个MDI子窗口

1 注册主窗口类型,创建子窗口

2 它的父窗口为MDICLIENT窗口

3 增加WS_EX_MDICHILD的风格

  HWND hWnd =

  CreateWindowEx( WS_EX_MDICHILD,

pszClassName, "ChildWnd",

WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, hParent, NULL,

g_hInst, NULL );

// WinMDI.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

HINSTANCE g_hInst = NULL;
HWND g_hMDIClient = NULL;

//主窗口的窗口处理函数
LRESULT CALLBACK MainProc( HWND hWnd,
						   UINT nMsg,
						   WPARAM wParam,
						   LPARAM lParam )
{
	switch( nMsg )
	{
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	}
	return DefFrameProc( hWnd, g_hMDIClient,
		nMsg, wParam, lParam );
}
//子窗口的窗口处理函数
LRESULT CALLBACK ChildProc( HWND hWnd,
						    UINT nMsg,
							WPARAM wParam,
							LPARAM lParam )
{
	return DefMDIChildProc( hWnd, nMsg,
		wParam, lParam );
}
//窗口注册函数
BOOL RegisterWnd( LPSTR   pszClassName,
				  WNDPROC Proc,
				  int     nBrush )
{
	WNDCLASSEX wce = { 0 };
	wce.cbSize     = sizeof( wce );
	wce.style      = CS_HREDRAW|CS_VREDRAW;
	wce.cbClsExtra = 0;
	wce.cbWndExtra = 0;
	wce.lpfnWndProc= Proc;
	wce.hInstance  = g_hInst;
	wce.hCursor    = NULL;
	wce.hIcon      = NULL;
	wce.hbrBackground = HBRUSH(nBrush);
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.hIconSm       = NULL;

	ATOM nAtom = RegisterClassEx( &wce );
	if( nAtom == 0 )
	{
		return FALSE;
	}
	return TRUE;
}
//显示窗口
void DisplayWnd( HWND hWnd )
{
	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );
}
//消息循环
void Message( )
{
	MSG msg = { 0 };
	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		DispatchMessage( &msg );
	}
}
//创建主窗口
HWND CreateMainWnd( LPSTR pszClassName )
{
	HWND hWnd = CreateWindowEx( 0,
		pszClassName, "MainWnd", 
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, NULL, NULL, g_hInst,
		NULL );
	return hWnd;
}
//创建MDICLIENT窗口
HWND CreateMDIClient( HWND hParent )
{
	CLIENTCREATESTRUCT cs = { 0 };
	cs.idFirstChild = 1000;
	HWND hWnd = CreateWindowEx( 0,
		"MDICLIENT", "MainWnd", 
		WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, hParent, NULL, g_hInst,
		&cs );
	return hWnd;
}
//创建MDI子窗口
HWND CreateChildWnd( LPSTR pszClassName, 
					 HWND hParent )
{
	HWND hWnd = CreateWindowEx( WS_EX_MDICHILD,
		pszClassName, "ChildWnd", 
		WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, hParent, NULL, g_hInst,
		NULL );
	return hWnd;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{	//注册主窗口
	RegisterWnd( "MainWnd", MainProc, 
		COLOR_BTNFACE+1 );
	//注册子窗口
	RegisterWnd( "ChildWnd", ChildProc,
		COLOR_WINDOW );
	//创建MDI主窗口
	HWND hMain = CreateMainWnd( "MainWnd" );
	//创建MDICLIENT窗口
	g_hMDIClient = CreateMDIClient( hMain );
	MoveWindow( g_hMDIClient, 0, 0, 500, 
		500, TRUE );
	//创建MDI子窗口
	CreateChildWnd( "ChildWnd", 
		g_hMDIClient );
	CreateChildWnd( "ChildWnd", 
		g_hMDIClient );
	CreateChildWnd( "ChildWnd", 
		g_hMDIClient );

	//显示和消息处理
	DisplayWnd( hMain );
	Message( );
	return 0;
}






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值