25win32编程基础——子窗口消息循环

本节我们学习一下子窗口的消息循环的过程:

首先我们创建1个win32的windows应用程序

 然后利用上篇的代码先创建1个窗口

// 21C++SonOfWindowLoop.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "21C++SonOfWindowLoop.h"
#include "Output.h"
#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst; ;								// 当前实例

LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	
	hInst= hInstance;
 	// TODO: 在此放置代码。
	//创建我们自己的窗口类
	WNDCLASS wc={0};//使用前必须初始化
	TCHAR WClassName[] =TEXT("My Class");
	wc.lpszClassName = WClassName;
	wc.hInstance = hInst;
	wc.lpfnWndProc = WndProc;
	wc.hbrBackground = (HBRUSH)COLOR_GRAYTEXT;
	//在系统里面注册
	RegisterClass(&wc);

	//创建窗体
	HWND hnd=CreateWindow(
		WClassName,
		TEXT("我的窗口"),
		WS_OVERLAPPEDWINDOW,
		10,
		10,
		600,
		400,
		NULL,
		NULL,
		hInst,
		NULL
		);

	//ShowWindow(hnd,SW_SHOW|SW_SHOWNORMAL);
	ShowWindow(hnd,SW_SHOW);
	MSG msg;
	BOOL bRet;

while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
		OutputDebugStringQ(L"%d\n",GetLastError());
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

	
	return 0;
}


//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

 然后加1个子窗口

  

// 21C++SonOfWindowLoop.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "21C++SonOfWindowLoop.h"
#include "Output.h"
#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst; ;								// 当前实例

LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);

void CreateButton(HWND  hnd);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	
	hInst= hInstance;
 	// TODO: 在此放置代码。
	//创建我们自己的窗口类
	WNDCLASS wc={0};//使用前必须初始化
	TCHAR WClassName[] =TEXT("My Class");
	wc.lpszClassName = WClassName;
	wc.hInstance = hInst;
	wc.lpfnWndProc = WndProc;
	wc.hbrBackground = (HBRUSH)COLOR_GRAYTEXT;
	//在系统里面注册
	RegisterClass(&wc);

	//创建窗体
	HWND hnd=CreateWindow(
		WClassName,
		TEXT("我的窗口"),
		WS_OVERLAPPEDWINDOW,
		10,
		10,
		600,
		400,
		NULL,
		NULL,
		hInst,
		NULL
		);
	CreateButton(hnd);


	//ShowWindow(hnd,SW_SHOW|SW_SHOWNORMAL);
	ShowWindow(hnd,SW_SHOW);
	MSG msg;
	BOOL bRet;

while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
		OutputDebugStringQ(L"%d\n",GetLastError());
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

	
	return 0;
}

void CreateButton(HWND hnd){
	//创建窗体
	HWND hBtnd=CreateWindow(
		TEXT("Button"),		//1
		TEXT("按钮"),
		WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_DEFPUSHBUTTON,		
		10,
		10,
		80,
		20,
		hnd,
		(HMENU)1001,		//当创建的为WS_CHID的时候,这个参数就成为子窗口编号
		hInst,
		NULL
		);
	HWND hftnd=CreateWindow(
		TEXT("Button"),		//1
		TEXT("复选框"),
		WS_CHILD|WS_VISIBLE|BS_CHECKBOX|BS_AUTOCHECKBOX,		
		10,
		40,
		80,
		20,
		hnd,
		(HMENU)1002,		//2
		hInst,
		NULL
		);
	HWND hDtnd=CreateWindow(
		TEXT("Button"),		//1
		TEXT("单选框"),
		WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON|BS_AUTORADIOBUTTON,		
		10,
		80,
		80,
		20,
		hnd,
		(HMENU)1003,		//2
		hInst,
		NULL
		);
	
};

//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

 从以上代码可以看出:

1、在windows中所有控件都是窗口

2、没有创建Button类,却可以直接使用,是因为这个Button类是windows提前给我们定义好的,定义方式类似于我们前边那样定义的,因此可以直接使用。

3、当使用CreateWindow创建子窗口WS_CHILD的类型的时候,菜单参数就成为这个子窗口的ID了。

问题1:

当windows为我们定义好了窗口类,我们虽然可以拿来使用,但是像之前的那样在窗口类中定义 回调函数和菜单等操作相当于系统也为我们做好了,

我们可以通过2个API找到windows为我们定义好的类名和回调函数。

	//创建窗体
	HWND hBtnd=CreateWindow(
		TEXT("Button"),		//1
		TEXT("按钮"),
		WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_DEFPUSHBUTTON,		
		10,
		10,
		80,
		20,
		hnd,
		(HMENU)1001,		//2
		hInst,
		NULL
		);

	TCHAR cName[20];
	GetClassName(hBtnd,cName,20);
	WNDCLASS Bt1cs;
	GetClassInfo(hInst,cName,&Bt1cs);
	OutputDebugStringQ(L"%s\n",Bt1cs.lpszClassName);
	OutputDebugStringF("%04x\n",Bt1cs.lpfnWndProc);

  查看输出可以看到

 类名是:Button

回调函数地址是:0x7700e6b0

那么问题2就产生了,当我们点击这个按钮之后,我们想添加一些按钮的处理方法,那我们应该加载哪里呢,因为回调函数系统已经为我们做好了,我们应该怎么办呢?

  先理解一下子窗口的消息传递过程:

 因此父窗口的回调函数应该这样写:

//系统不停的调用回调函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);//取低2字节
		wmEvent = HIWORD(wParam);//取高2字节
		// 分析菜单选择:
		switch (wmId)
		{
		case 1001:
			OutputDebugStringF("按下%d\n",wmId);
			break;
		case 1002:
			OutputDebugStringF("按下%d\n",wmId);
			break;
		case 1003:
			OutputDebugStringF("按下%d\n",wmId);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_LBUTTONDOWN:
		OutputDebugStringF("按下左键\n");
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

  

 

posted @ 2023-10-24 11:31  一日学一日功  阅读(229)  评论(0)    收藏  举报