《Windows程序设计》读书笔九 子窗口控件

本文详细介绍了Windows程序设计中子窗口控件的使用,包括按钮、复选框、编辑框、列表框等标准控件的创建、属性设置及交互方式。通过WM_COMMAND消息、BM_SETSTATE等消息实现父窗口与子窗口的通信,讲解了如何改变控件状态、处理用户输入。同时,讨论了滚动条和编辑框的使用,以及如何处理WM_CTLCOLORBTN等消息以自定义控件颜色。
摘要由CSDN通过智能技术生成

第九章 子窗口控件

子窗口可以作为控制屏幕图形显示,响应用户输入,以及在有重要输入事件的时候通知另一窗口。


标准子窗口控件,按钮,复选框,编辑框,列表框,组合框,文本字符串和滚动条。


可以使用CreateWindow来创建子窗口控件,或者在程序的资源脚本里编辑好各种属性。


使用预定义控件不需要再注册相应的子窗口类,这些类已经存在于windows中并且已经有了预定义的名称。

在调用CreateWindow时,只需要使用该名称作为窗口类的参数即可。


在窗口表明直接创建子窗口,所涉及的任务比使用对话框内的子窗口控件更底层。对于对话框,对话框管理器在你的程序和控件之间增加了一个隔离层。

比如支持TAB,方向键切换焦点。 子窗口控件可以得到输入焦点,可是一旦得到焦点,它就无法把输入焦点交回给其父窗口。


标准控件, 通用控件。


9.1 按钮类

#include <windows.h>    

struct  
{
	int		iStyle;
	TCHAR * szText;
}
button[] = 
{
	BS_PUSHBUTTON,		TEXT("PUSHBUTTON"),
	BS_DEFPUSHBUTTON,	TEXT("DEFPUSHBUTTON"),
	BS_CHECKBOX,		TEXT("CHECKBOX"),
	BS_AUTOCHECKBOX,	TEXT("AUTOCHECKBOX"),
	BS_RADIOBUTTON,		TEXT("RADIOBUTTON"),
	BS_3STATE,			TEXT("3STATE"),
	BS_AUTO3STATE,		TEXT("AUTO3STATE"),
	BS_GROUPBOX,		TEXT("GROUPBOX"),
	BS_AUTORADIOBUTTON,	TEXT("AUTORADIO"),
	BS_OWNERDRAW,		TEXT("OWNERDRAW")
};

#define NUM (sizeof button / sizeof button[0])

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.    

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	PSTR szCmdLine, int iCmdShow)
{
	static      TCHAR szAppName[] = TEXT("BtnLook");
	HWND        hwnd;
	MSG         msg;
	WNDCLASS    wndClass;       //The window Class    

	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.    
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = szAppName;

	//Register the Window Class to the Windows System.     
	if (!RegisterClass(&wndClass))
	{
		MessageBox(NULL, TEXT("This program require Windows NT!"),
			szAppName, MB_ICONERROR);
		return 0;
	}

	//This function will generate an WM_CREATE message.    
	hwnd = CreateWindow(szAppName,      //Window class name    
		TEXT("Button Look"),      //Window caption    
		WS_OVERLAPPEDWINDOW,            //Window Style    
		CW_USEDEFAULT,                  //initial x position    
		CW_USEDEFAULT,                  //initial y position    
		CW_USEDEFAULT,                  //initial x size    
		CW_USEDEFAULT,                  //initial y size    
		NULL,                           //parent window handle    
		NULL,                           //window menu handle    
		hInstance,                      //program instance handle    
		NULL);                          //creation parameters    

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd); //This function will generate a WM_PAINT message.    

						/* The message loop for this program.
						if received the WM_QUIT message, the function will return 0.*/
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;

}

//define the Window Procedure WndProc    
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND		hwndButton[NUM];
	static RECT		rect;
	static TCHAR	szTop[] =		TEXT("message            wParam       lParam"),
					szUnd[] =		TEXT("_______            ______       ______"),
					szFormat[] =	TEXT("%-16s%04X-%04X    %04X-%04X"),
					szBuffer[50];
	static int		cxChar, cyChar;
	HDC				hdc;
	PAINTSTRUCT		ps;
	int				i;

	switch (message) //get the message    
	{
	case WM_CREATE:
		cxChar = LOWORD(GetDialogBaseUnits());
		cyChar = HIWORD(GetDialogBaseUnits());

		for (i = 0; i < NUM; i++)
			hwndButton[i] = CreateWindow(TEXT("button"),
				button[i].szText,
				WS_CHILD | WS_VISIBLE | button[i].iStyle,
				cxChar, cyChar * (1 + 2 * i),
				20 * cxChar, 7 * cyChar / 4,
				hwnd, (HMENU)i,
				((LPCREATESTRUCT)lParam)->hInstance, NULL);
		return 0;

	case WM_SIZE:
		rect.left = 24 * cxChar;
		rect.top = 2 * cyChar;
		rect.right = LOWORD(lParam);
		rect.bottom = HIWORD(lParam);
		return 0;

	case WM_PAINT:
		InvalidateRect(hwnd, &rect, TRUE);

		hdc = BeginPaint(hwnd, &ps);

		SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
		SetBkMode(hdc, TRANSPARENT);

		TextOut(hdc, 24 * cxChar, cyChar, szTop, lstrlen(szTop));
		TextOut(hdc, 24 * cxChar, cyChar, szUnd, lstrlen(szUnd));

		EndPaint(hwnd, &ps);
		return 0;

	case WM_DRAWITEM:
	case WM_COMMAND:
		ScrollWindow(hwnd, 0, -cyChar, &rect, &rect);

		hdc = GetDC(hwnd);
		SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

		TextOut(hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1),
			szBuffer,
			wsprintf(szBuffer, szFormat,
				message == WM_DRAWITEM ? TEXT("WM_DRAWITEM") :
										 TEXT("WM_COMMAND"),
				HIWORD(wParam), LOWORD(wParam),
				HIWORD(lParam), LOWORD(lParam)));

		ReleaseDC(hwnd, hdc);
		ValidateRect(hwnd, &rect);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return  DefWindowProc(hwnd, message, wParam, lParam);
}

9.1.1 创建子窗口


GetDialogBaseUnits 来获得字符默认的字体的宽度和高度。 低位和高位分别是宽度和高度

与GetTextMetrics返回类似的数据

  1.     GetTextMetrics(hdc, &tm);  
  2.     cxChar = tm.tmAveCharWidth;  
  3.     cyChar = tm.tmHeight + tm.tmExternalLeading;  

每个子窗口的ID是唯一的


在WM_CREATE消息中lParam 是一个指向CREATESTRUCT结构的指针。  hInstance是改结构的成员  即 ( (LPCREATESTRUCT)lParam)->hInstance,

或者

 (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE)

9.1.2 子窗口传递信息给父窗口

点击按钮时,子窗口发送WM_COMMAND 消息给父窗口。

LOWORD(wParam)   子窗口ID

HIWORD(wParam) 通知码

lParam    子窗口句柄


通知码定义


通知码6,7 只有当包含 BS_NOTIFY样式时才会启用

子窗口有输入焦点以后,所有的键盘消息都会送到这个子窗口控件,而不是主窗口。按钮控件一旦获得输入焦点,就会忽略所有按键操作,但空格键除外,此时空格键具有和单击鼠标一样的效果。


9.1.3 父窗口传递信息给子窗口



例如父窗口发送 BM_GETCHECK BM_CHECK 给子窗口控件,以获得和设置复选框和单选框的选择状态。

在用鼠标或空格点击窗口时,BM_GETSTATE 和 BM_SETATETE消息反应一个窗口的状态是正常的还是被单击了。

BM_SETSTYLE 允许在创建按钮后改变按钮的样式。


id=GetWindowLong(hwndChild, GWL_ID);


id = GetDlgCtrlID (hwndChild);


hwndChild = GetDlgItem(hwndParent, id);


9.1.4 按钮

按钮控件 ,调用CreateWindow 或者MoveWindow可以改变其大小和位置, 是一个矩形。 按钮上显示文字

BS_PUSHBUTTON

BS_DEFPUSHBUTTON 较重的轮廓

按钮最佳视觉高度是字符高度的 7/4, 而宽度需要额外容纳两个文本


给子窗口发送BM_SETSTATE消息可以模拟按钮状态变化

SendMessage(hwndButton, BM_SETSTATE, 1, 0);   //按钮被按下

SendMessage(hwndButton, BM_SETSTATE, 0, 0);  //按钮回到正常状态

也可以给按钮发送一个BM_GETSTATE消息,子窗口控件返回当前按钮的状态。如果按钮时按下返回TRUE,否则FALSE.


9.1.5 复选框

checkBox

文本通常出现在复选框右侧,如果包含 BS_LEFTTEXT样式,则出现在左侧; 组合BS_RIGHT样式使文本右对齐

BS_CHECKBOX

必须给控件发送一个BM_SETCHECK消息来设置其选中标记。 wParam 设置1 会选中标记, 0则清楚标记。

发送BM_GETCHECK来获得复选框当前的状态。


在处理WM_COMMAND消息的时候

SendMessage((HWND)lParam , BM_SETCHECK, (WPARAM) 

! SendMessage((HWND)lParam, BM_GETCHECK, 0, 0 ), 0 );


BS_AUTOCHECKBOX

按钮本身负责切换选定和取消标记,可以忽略WM_COMMAND消息

在需要按钮状态时

iCheck = (int) SendMessage(hwndButton, BM_GETCHECK, 0, 0 );      //选中为TRUE ,否则为FALSE


另外 BS_3STATE 和  BS_AUTO3STATE 有3种状态   BM_SETCHECK消息射wParam 为 2 表示灰色

复选框最低高度是一个字符高度,最小宽度是现有字符再加2个字符宽度。


9.1.6 单选按钮

任意时刻只有一个按钮可以被按下。

BS_RADIOBUTTON,  BS_AUTORADIOBUTTON(只用于对话框)

在处理WM_COMMAND消息是应该向其发送消息表明其选中

SendMessage((HWND)lParam, BM_SETCHECK, 1, 0);

发送以下消息表明取消选中

SendMessage((HWND)lParam, BM_SETCHECK, 0, 0);


9.1.7 组合框

GroupBox

通常用来包容其他类型的控件


9.1.8  改变按钮文本

可以调用SetWindowText 来改变按钮的文本

SetWindowText(hwnd, pszString); //包括主窗口和子窗口


iLength = GetWindowText(hwnd, pszBuffer, iMaxLength); //获得窗口当前的文本 Caption属性


可以调用函数使程序对可以接受特定文本长度有所准备

iLength = GetWindowTextLength(hwnd);


9.1.9 可见的按钮和启动的按钮

如果创建子窗口未包含WM_VISIBLE 按钮时不可见的,除非调用

ShowWindow(hwndChild, SW_SHOWNORMAL);

如果窗口可见可以隐藏他

ShowWindow(hwndChild, SW_HIDE);

可以调用一下函数判断窗口是否可见

IsWindowVisible(hwndChild);

启用或禁用子窗口

EnableWindow(hwndChild, FALSE);


EnableWindow(hwndChild, TRUE);


调用一下函数判断子窗口是否被启用

IsWindowEnabled(hwndChild);


9.1.10 按钮和输入焦点

子窗口控件获得输入焦点后,父窗口就会失去输入焦点。之后所有的键盘输入将送到子窗口而不是其父窗口。


Windows把输入焦点从一个窗口切换到另一个窗口时,它首先会像要失去输入焦点的窗口发送一条消息WM_KILLFOCUS. 相应的wParam参数是将要获得输入焦点的窗口的句柄。然后Windows向要接受输入焦点的窗口发送WM_SETFOCUS消息,用wParam指定失去输入焦点的窗口的句柄。

父窗口可以通过WM_KILLFOCUS消息来阻止子窗口控件获得输入焦点。

	case WM_KILLFOCUS:
		for (i = 0; i < NUM; i++)
			if (hwndButton[i] == (HWND)wParam)
			{
				SetFocus(hwnd);
				break;
			}
这样子窗口将不会获得输入焦点

或者

	case WM_KILLFOCUS:
		if (hwnd == GetParent((HWND)wParam))
			SetFocus(hwnd);

单这么做以后按钮将不能再响应消息。因为按钮从未得到输入焦点。

9.2 控件和颜色

9.2.1 系统颜色

windows有29种系统颜色来支持各部分显示。可以使用GetSysColor 和SetSysColor获取并设置这些颜色。





9.2.2 按钮的颜色

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值