一、
我知道用VB写程序就是直接托控件的,MFC也是托控件的,那win32 API编程怎么实现那样的控件呢?嘿嘿,现在学到了。
创建控件就用CreateWindow函数实现。CreateWindow函数有一个参数是HWND,就是父窗口的句柄,这么说来就可以有子窗口了嘛。还有第1个参数是窗口类型,利用这个参数就可以创建不同的控件了,比如:按钮(BUTTON),编辑框(edit),文本框等。
CreateWindow("Button","退出",WS_VISIBLE|WS_CHILD,10,10, 50,30, hwnd,NULL,hInstance,NULL);
WS_VISIBLE是可见,就是可以在窗口上面显示出来吧,WS_CHILD是说这个窗口是个子窗口,hwnd是父窗口的句柄了。就这么一句就可以看到一个长50,宽30的按钮了。
但是,现在一个问题是,这个函数要写在哪里呢?我试了2个地方,第一个地方就是父窗口创建完后,紧接着就创建这个按钮。第二个地方嘛,就在消息处理函数里面了。
父窗口创建完后会有一个WM_CREATE消息,那现在这个按钮就可以写在这个消息的处理里面了。
case WM_CREATE:
//CreateWindow(TEXT("Button"),TEXT("退出"),WS_VISIBLE|WS_CHILD,10,10, 50,30, hwnd,,hg_app,NULL);
但是这样的话有个问提,就是倒数第二个参数,窗口实例句柄(什么是窗口实例句柄,我还不太明白,额...),这个参数写什么呢?试一下吧,就写父窗口的那个hInstance吧,那就需要定义一个全局变量了,嗯,就定义一个:HINSTANCE hg_app;
那现在就给它赋值,就在WinMain函数里面吧,我这里就写在父窗口创建完后吧!hg_app = hInstance;
额...貌似完成了,运行下,发现那个按钮出现了。
但是呢,现在点击这个按钮是没有作用的,因为还没有给它写上代码做啥事情,那就写一个吧!
这个按钮控件,按下去了会发送一个WM_COMMAND消息,但是知道了是这个消息,那怎么是知道是这个按钮呢(如果有很多的按钮)?所以它也应该有个ID吧!但是创建控件的时候没有ID这个项呀!
原来,它和菜单一样啊,菜单的ID是怎么获取得到的?LOWORD(wparam)就是这个,是在消息处理函数里面的wparam参数里面取来的。LOWOR就是一个宏,就是转换为WORD类型的,WORD类型就是unsigned short。因为菜单的ID是在wparam这个参数的低位存放的。
那这个控件的ID也跟菜单一样写就是了,菜单的ID是写在哪里的?我创建菜单是用资源文件生成的,那我就不知道这个控件的ID写在哪里了。不过,总算还是从别的地方知道了,CreateWindow函数有个参数是指定菜单的,那这个控件是没有菜单的,那就用这个菜单当作ID了,我就给他取一个ID名字叫做IDC_BUTTON吧:
CreateWindow("Button","退出",WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,10,10, 50,30, hwnd,(HMENU)IDC_BUTTON,hInstance,NULL);
现在IDC_BUTTON是个没有定义的,先看看菜单,每项的定义都是在头文件resource.h中,那这里我就在程序的头部定义吧:
#define IDC_BUTTON 40004
那现在就响应这个按钮吧!
case IDC_BUTTON:
MessageBox(hwnd,"程序将退出","提示",MB_OK|MB_ICONQUESTION);
PostQuitMessage(0);//终止程序
下面看看完整程序:
#include "Windows.h"
#include "resource.h"
#define IDC_BUTTON 40004
void ShowErrMsg()
{
//TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
MessageBox(NULL, (LPTSTR)lpMsgBuf, "系统错误", MB_OK|MB_ICONSTOP);
//OutputDebugString();
LocalFree(lpMsgBuf);
}
LRESULT CALLBACK WinProc(HWND hwnd,UINT umsg,WPARAM wparam,LPARAM lparam);
HINSTANCE hg_app;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrecInstance,
LPSTR lpCmdLine,
int nShowCmd
)
{
TCHAR* clsName="myclass";
WNDCLASS mwc={sizeof(WNDCLASS)};
//设计窗口类
mwc.lpfnWndProc = WinProc; //窗口处理函数
mwc.hbrBackground = (HBRUSH)COLOR_WINDOW; //窗口背景色
mwc.lpszClassName = clsName; // 窗口类名
mwc.style = CS_HREDRAW | CS_VREDRAW; //窗口类型
mwc.cbClsExtra = 0; //窗口扩展
mwc.cbWndExtra = 0; //窗口实例扩展
mwc.lpszMenuName = MAKEINTRESOURCE(IDR_MENUmain); //窗口菜单
//mwc.lpszMenuName = (CHAR *)IDR_MENUmain;
mwc.hInstance = hInstance; //实例句柄
//注册窗口类
RegisterClass(&mwc);
//创建窗口
HWND hwnd = CreateWindow(
clsName, //类名,就是刚才注册的
//"HEHE",
TEXT("Windows的标题"), //窗口标题
WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, //外观样式
400, //相对于父窗口的X坐标
150, //相对于父窗口的Y坐标
400, //窗口的宽
400, //窗口的高
NULL, //父窗口,没有就写NULL
0,
//LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENUmain)), //窗口菜单,也没有,写NULL
hInstance, //当前应用程序的实例句柄
NULL); //附加数据,没有,为NULL
if( hwnd == NULL) //检查窗口是否创建成功
{
ShowErrMsg();
//DWORD err = GetLastError();
//TCHAR er[123] ;
//wsprintf(er,"%i",err);
//MessageBox(NULL,er,TEXT("提示"),MB_ICONWARNING);
MessageBox(NULL,TEXT("创建窗口失败"),TEXT("提示"),MB_ICONWARNING);
return 0;
}
//显示窗口和更新窗口
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
CreateWindow("Button","退出",WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,10, 10, 50, 30, hwnd,(HMENU)IDC_BUTTON, hInstance,NULL);
hg_app = hInstance;
//消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//MessageBox(NULL,TEXT("你好 Windows 世界^_^"),TEXT("标题"),MB_OK);
return 0;
}
LRESULT CALLBACK WinProc(HWND hwnd,UINT umsg,WPARAM wparam,LPARAM lparam)
{
switch(umsg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd,&ps);
DrawText(ps.hdc,TEXT("你好啊"),6,&(ps.rcPaint),DT_CENTER);
EndPaint(hwnd,&ps);
}
return 0;
case WM_CREATE:
//CreateWindow(TEXT("Button"),TEXT("退出"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, 10, 10, 50, 30, hwnd,(HMENU)IDC_BUTTON,hg_app,NULL);
return 0;
case WM_COMMAND:
{
HMENU hm=GetMenu(hwnd); //获取菜单句柄
HMENU hsm = GetSubMenu(hm,1); //获取菜单下级的菜单句柄
switch(LOWORD(wparam))
{
case IDM_EXIIT: PostQuitMessage(0);
break;
case IDM_ABOUT:
CheckMenuItem(hm,IDM_ABOUT,MF_CHECKED); //选中
break;
case IDM_HELP:
CheckMenuRadioItem(hsm,IDM_ABOUT,IDM_HELP,IDM_HELP,MF_BYCOMMAND); //单选项
break;
case IDC_BUTTON:
MessageBox(hwnd,"程序将退出","提示",MB_OK|MB_ICONQUESTION);
PostQuitMessage(0); //终止程序
break;
default:
break;
}
}
return 0;
case WM_DESTROY:
{
PostQuitMessage(0); //终止程序
return 0;
}
}
return DefWindowProc(hwnd,umsg,wparam,lparam);
}
看到了,按下“退出”按钮就提示这么个消息!
二、
现在可以试着改下风格,创建一个编辑框把,能够输入文字的。
就是修改下CreateWindow函数的第一个参数,就可以了:
CreateWindow("edit","退出",WS_VISIBLE|WS_CHILD|BS_AUTORADIOBUTTON ,10, 10, 150, 30, hwnd,(HMENU)IDC_BUTTON, hInstance,NULL);
这样就可以看到一个文本框了。
还有其他更多的,日后慢慢学习。