#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) ;//首先是一个回调函数的声明
int WINAPI WinMain (HINSTANCE hInstance,//应用程序当前实例的句柄
HINSTANCE hPrevInstance,//应用程序先前的实例句柄
PSTR szCmdLine, //指向应用程序命令行的字符串的指针
int iCmdShow)//指明窗口如何显示
{
static TCHAR szAppName[] = TEXT ("BtnLook") ;
HWND hwnd ;//当前实例的句柄
MSG msg ;//消息
WNDCLASS wndclass ;//类名
wndclass.style = CS_HREDRAW | CS_VREDRAW ;//窗口的显示方式,此处为水平重画和竖直重画
wndclass.lpfnWndProc = WndProc ;//窗口回调函数
wndclass.cbClsExtra = 0 ;//窗口扩展,此处为0
wndclass.cbWndExtra = 0 ;//窗口实例扩展,此处为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 ;//窗口菜单,此处没菜单设为NULL
wndclass.lpszClassName = szAppName ;//窗口类名
if (!RegisterClass (&wndclass))//注册窗口,若注册失败,产生如下的信息
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
///创建窗口,如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL
hwnd = CreateWindow (szAppName,
TEXT ("Button Look"),//窗口的名字
WS_OVERLAPPEDWINDOW,//窗口的创建风格
CW_USEDEFAULT,//指定窗口的初始水平位置
CW_USEDEFAULT,//指定窗口的初始垂直位置
CW_USEDEFAULT,//以设备单元指明窗口的宽度。若是CW_USEDEFAULT,则系统为窗口选择一个缺省的宽度
CW_USEDEFAULT,//以设备单元指明窗口的高度。
NULL,//指向被创建窗口的父窗口或所有者窗口的句柄,此处为NULL
NULL,//菜单句柄,或依据窗口风格指明一个子窗口标识,此处为NULL
hInstance, //与窗口相关联的模块实例的句柄
NULL) ;//指向一个值的指针,该值传递给窗口WM_CREATE消息
ShowWindow (hwnd, iCmdShow) ;//显示窗口,hWnd:指窗口句柄。iCmdShow:指定窗口如何显示
UpdateWindow (hwnd) ;//更新窗口,hWnd:指窗口句柄
while (GetMessage (&msg, NULL, 0, 0))//消息循环
{
TranslateMessage (&msg) ;//该函数将虚拟键消息转换为字符消息
DispatchMessage (&msg) ;//该函数分发一个消息给窗口程序
}
return msg.wParam ;//wParam是消息携带的参数,可以是个值,也可以是个地址
}
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)
{
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;//该函数返回系统的对话基本单位,该基本单位为系统字体字符的平均宽度和高度
cyChar = HIWORD (GetDialogBaseUnits ()) ;//同上
//用for循环为NUM个按钮控件创建句柄
for (i = 0 ; i < NUM ; i++)
hwndButton[i] = CreateWindow ( TEXT("button"),
button[i].szText,//按钮的名字
WS_CHILD | WS_VISIBLE | button[i].iStyle,//按钮类的风格
//WS_CHILD表示生成的窗口是母窗口的子窗口
//WS_VISIBLE创建一个可见的窗口
//button[i].iStyle这个参数我不知道。。。
cxChar, //按钮的x坐标
cyChar * (1 + 2 * i),//按钮的Y坐标
20 * cxChar, //按钮的宽度
7 * cyChar / 4,//按钮的高度
hwnd, //父窗口的句柄
(HMENU) i,//指明该子窗口的标识
((LPCREATESTRUCT) lParam)->hInstance, //该按钮的句柄
NULL) ;
return 0 ;
case WM_SIZE :
rect.left = 24 * cxChar ;//left : 指定矩形框左上角的x坐标
rect.top = 2 * cyChar ;//top: 指定矩形框左上角的y坐标
rect.right = LOWORD (lParam) ;//right: 指定矩形框右下角的x坐标
rect.bottom = HIWORD (lParam) ;//bottom:指定矩形框右下角的y坐标
return 0 ;
case WM_PAINT :
InvalidateRect (hwnd, &rect, TRUE) ;//该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制
hdc = BeginPaint (hwnd, &ps) ;//获取环境句柄
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
//SelectObject函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象
//GetStockObject函数检索预定义的备用笔、刷子、字体或者调色板的句柄
//SYSTEM_FIXED_FONT为固定间距(等宽)系统字体
SetBkMode (hdc, TRANSPARENT) ;
//TRANSPARENT是使用透明的输出,也就是文字的背景是不改变的
TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ;
TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ;
//TextOut函数用当前选择的字体、背景颜色和正文颜色将一个字符串写到指定位置
//第一个参数为设备句柄
//第二个参数为字符串的开始位置 x坐标
//第三个参数为字符串的开始位置 y坐标
//第四个参数为 字符串
//第五个参数为字符串的长度
EndPaint (hwnd, &ps) ;//释放句柄
return 0 ;
case WM_DRAWITEM ://一般此消息在控件需要重画时发出,在收到此消息之后控件才会执行重画
case WM_COMMAND ://当一个控件发送通知消息去给父窗口或者按下一个快捷键将发送 WM_COMMAND 消息
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;//该函数滚动所指定的窗口客户区域内容
//第一个参数为客户区域将被滚动的窗口的句柄
//第二个参数为指定水平滚动的距离,以设备单位计。当向左滚动窗体内容时,参数值必须为负
//第三个参数为指定垂直滚动的距离,以设备单位计。当向上滚动窗体内容时,参数值必须为负
//第四个参数为指向RECT结构的指针,该结构指定了将要滚动的客户区范围。若此参数为NULL,则整个客户区域将被滚动
//第五个参数为指向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) ;//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
}
我有一个地方不懂,就是WM_COMMAND里面的TextOut函数里面的wsprintf函数不懂,里面的参数不够清除