开始新的学习了.
从今天下午开始,正式开始接触了一下Windows SDK.
发现原来用这个东西弄起程序来,异常的麻烦啊!建个窗体都要N多行代码.
(大部分来源于VC++深入详解中的WinMain一章)
大致的代码流程是
首先包含Windows.h这个头文件
然后,就是程序的入口函数,和C语言的不同,其入口函数不是main而是WinMain.原形如下:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
先看前面的修饰符号
WINAPI利用goto definition功能查看WINAPI的定义,可以看到WINAPI其实就是__stdcall。也就是一种调用
的时候函数参数的传递方式了
hInstance就是指当前应用程序的实例句柄,在Delphi中也是有一个hinstance,想想也应该就是这样的一个句柄吧.
这是一个数值。当程序在Windows下运行时,它唯一标识运行中的实例(注意,只有运行中的程序实例,才有实例句柄)。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个句柄值,并通过hInstance参数传递给WinMain函数。
hPrevInstance表示当前实例的前一个实例的句柄。通过查看MSDN我们可以知道,在Win32环境下,这个参数总是NULL,即在Win32环境下,这个参数不再起作用。其存在的目的是兼容以前的程序.
szCmdLine是一个以空终止的字符串,指定传递给应用程序的命令行参数。例如:在D盘下有一个sunxin.txt文件,当我们用鼠标双击这个文件时将启动记事本程序(notepad.exe),此时系统会将D:/sunxin.txt作为命令行参数传递给记事本程序的WinMain函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。要在VC++开发环境中向应用程序传递参数,可以单击菜单【Project】→【Settings】,选择“Debug”选项卡,在“Program arguments”编辑框中输入你想传递给应用程序的参数。
iCmdShow指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,应用程序通常不需要去理会这个参数的值。
WinMain入口函数的参数的意思明白了,则进入到一个简单的程序.呵呵,我没有使用大师级常用的
Hello World作为第一个程序.而是创建一个窗体.呵呵,初学来着.
要创建窗体,首先就是要 注册一个窗口类,然后才可根据注册的窗体类的类名使用CreateWindow来创建一个窗体
注册窗体类.
使用RegisterClass函数来注册.该函数需要一个WNDCLASS结构的参数.
关于该结构的说明,请看我转的一篇文章
HWND CreateWindow(
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
HANDLE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
父
窗
口
|
子
窗
口
|
销毁
|
在父窗口被销毁之前销毁
|
隐藏
|
在父窗口被隐藏之前隐藏,子窗口只有在父窗口可见时可见
|
移动
|
跟随父窗口客户区一起移动
|
显示
|
在父窗口显示之后显示
|
(1)从消息队列中获取消息还可以调用PeekMessage函数,该函数的原型声明如下所示:
BOOL PeekMessage(
LPMSG lpMsg, // message information
HWND hWnd, // handle to window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax, // last message
UINT wRemoveMsg // removal options
);
前4个参数和GetMessage函数的4个参数的作用相同。最后1个参数指定消息获取的方式,如果设为PM_NOREMOVE,那么消息将不会从消息队列中被移除;如果设为PM_REMOVE,那么消息将从消息队列中被移除(与GetMessage函数的行为一致)。关于PeekMessage函数的更多信息,请参见MSDN。
(2)发送消息可以使用SendMessage和PostMessage函数。SendMessage将消息直接发送给窗口,并调用该窗口的窗口过程进行处理。在窗口过程对消息处理完毕后,该函数才返回(SendMessage发送的消息为不进队消息)。PostMessage函数将消息放入与创建窗口的线程相关联的消息队列后立即返回。除了这两个函数外,还有一个PostThreadMessage函数,用于向线程发送消息,对于线程消息,MSG结构体中的hwnd成员为NULL。
呵呵,抄了一大把,下面,附上一段代码.
#include <windows.h>
HINSTANCE AppInstance;
int CmdShow;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//处理感兴趣的消息
switch (message)
{
case WM_DESTROY:
//当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环
PostQuitMessage (0) ;
return 0 ;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"想要结束吗?","message",MB_YESNO))
{
DestroyWindow(hwnd);
}
break;
default://默认窗口消息处理
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
//其他消息交给由系统提供的缺省处理函数
return 0;
}
HWND CreateForm(TCHAR* ClassFormName,TCHAR *Caption)
{
WNDCLASS wndclass ;
HWND hwnd;
wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;//窗体样式
wndclass.lpfnWndProc = WindowProc;//关联消息处理函数
wndclass.cbClsExtra = 0 ;//表示窗口类结构之后分配的额外的字节数。系统将该值初始化为0
wndclass.cbWndExtra = 0 ;//表示窗口实例之后分配的额外的字节数。系统将该值初始化为0.如果使用资源文件里的CLASS指令
//创建对话框,并用WNDCLASS注册该对话框时,cbWndExtra必须设置成DLGWNDOWEXTRA。
wndclass.hInstance = AppInstance;//应用程序实例句柄
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; //图标
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; //光标
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); //画刷
wndclass.lpszMenuName = NULL ;//菜单资源名称
wndclass.lpszClassName = ClassFormName;//类名称
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT (strcat("注册窗体类",strcat(ClassFormName,"失败!"))),
ClassFormName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (ClassFormName, //窗口类名称
TEXT (Caption), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口风格
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
AppInstance, //实例句柄
NULL);
ShowWindow (hwnd, CmdShow) ;
UpdateWindow (hwnd) ;
return hwnd;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
AppInstance = hInstance;
CmdShow = iCmdShow;
CreateForm("TForm1","test");
//消息循环
MSG msg ;
while (GetMessage (&msg, NULL, 0, 0)) //从消息队列中取消息
{
TranslateMessage (&msg) ; //转换消息
DispatchMessage (&msg) ; //派发消息
}
return msg.wParam ;
}
按照Delphi的设想来的,如此一想,写一个Form类,应该也不难的吧!按照OOP的思想把这些底层的创建按照自己的思想封装一下.