下面就SDK编程写出一个简单的例子来做示例:
1 首先新建一个VC2005的空项目,在项目中,添加一个CPP源文件,取名叫做WinMain.cpp.
2 添加如下代码:
#include <Windows.h>
#include <stdio.h>
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
#define D(x) {OutputDebugStringA( x"/r/n" );}
int WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//设计窗口类
WNDCLASS wndclass;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.hCursor=LoadCursor(hInstance,IDC_HELP);
wndclass.hIcon=LoadIcon(hInstance,IDI_ERROR);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=WindowProc;
wndclass.lpszClassName="RockForm";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
//注册窗口类
RegisterClass(&wndclass);
//创建类对象
HWND hwnd ;
hwnd=CreateWindow(wndclass.lpszClassName,"达迅伟业",WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_NORMAL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg,hwnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch(uMsg)
{
case WM_CREATE:
{
D("WM_CREATE");
}
break;
case WM_NCPAINT: //Frame Work
{
D("WM_NCPAINT");
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
break;
case WM_PAINT:
{
D("WM_PAINT");
HDC hdc;
PAINTSTRUCT paintstruct;
hdc=BeginPaint(hwnd,&paintstruct);
EndPaint(hwnd,&paintstruct);
}
break;
case WM_ERASEBKGND:
{
D("WM_ERASEBKGND");
}
break;
case WM_CLOSE:
{
D("WM_CLOSE");
}
break;
case WM_DESTROY:
{
D("WM_DESTROY");
}
break;
case WM_CHAR:
{
D("WM_CHAR");
char szChar[20];
sprintf(szChar,"char is %d",wParam);
MessageBox(hwnd,szChar,"weixin",0);
}
break;
case WM_LBUTTONDOWN:
{
D("WM_LBUTTONDOWN");
HDC hdc=GetDC(NULL);
int _PreMode= SetBkMode(hdc,TRANSPARENT);
TextOut(hdc,10,10,"显示在屏幕上面,而不是显示在窗体上面",strlen("显示在屏幕上面,而不是显示在窗体上面"));
//SetBkMode(hdc,_PreMode);
ReleaseDC(NULL,hdc);
}
break;
case WM_LBUTTONUP:
{
D("WM_LBUTTONUP");
HDC hdc=GetDC(hwnd);
TextOut(hdc,10,10,"你现在好吗?",strlen("你现在好吗?"));
ReleaseDC(hwnd,hdc);
}
break;
case WM_RBUTTONDOWN:
{
D("WM_RBUTTONDOWN");
HDC hdc=GetDC(NULL);
//int _PreMode= SetBkMode(hdc,TRANSPARENT);
TextOut(hdc,10,10,"WM_RBUTTONDOWN 显示在屏幕上面的,没有Mode处理",strlen("WM_RBUTTONDOWN 显示在屏幕上面的,没有Mode处理"));
//SetBkMode(hdc,_PreMode);
ReleaseDC(NULL,hdc);
}
break;
case WM_RBUTTONUP:
{
D("WM_RBUTTONUP");
HDC hdc=GetDC(hwnd);
TextOut(hdc,10,10,"WM_RBUTTONUP, 显示在窗体上面的。",strlen("WM_RBUTTONUP, 显示在窗体上面的。"));
ReleaseDC(hwnd,hdc);
}
break;
case WM_MOVE:
{
D("WM_MOVE");
}
break;
case WM_MOVING:
{
D("WM_MOVING");
}
break;
default:
{
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
break;
}
return 0;
}
3 :这样我们就完成了基本的SDK编程,由此我们可以看出微软的东西的基本架构就出现了,理解了它的基本架构,我们就好理解了.
下面就这段代码来做个笔记,备忘录。
- 函数的入口地址,WinMain函数,程序是以这个为入口点,顺序执行,执行到代码的最后出,也就推出了,这个程序也就完成了。进程结束了。
- 窗体创建的基本过程:
- 设计窗口类WNDCLASS wndclass
- 注册窗口类RegisterClass
- 创建窗口类的实例HWND hwnd=CreateWindow()
- 显示窗口ShowWindow
3.windows是基于消息的机制,程序要保持一直运行,靠的就是消息机制来完成。
GetMessage():从消息队列中取走消息,当没有消息可以取的时候,函数就阻塞在那,直到消息队列中有消息过来。只要取得的消息不是WM_QUIT消息,返回值就为非零,消息循环得以维持。
PeekMessage(),从消息队列总取出消息,可以取走,也可以仅仅是取出。
TranslateMesage():translates virtual-key messages into character messages,The character messages are posted to the calling thread's message queue, to be read the next time the thread calls the GetMessage or PeekMessage function。
DispatchMessage():dispatches a message to a window procedure. It is typically used to dispatch a message retrieved by the GetMessage function.把装换来的消息分发给消息过程处理函数。
4:WindowProc 消息过程处理函数,这个函数一定是静态函数,也就是全局函数,在编译时已经确定了地址。由于它需要设置在注册的窗口类型里,可以从上面的代码中看出来。
5:DefWindowProc:MS给系统定义了许多的消息,在使用的时候我们只需要针对我们需要修改的消息来进行处理,其他的消息或者我们不希望处理的部分,我们把它交给系统来处理,系统可以维护一些我们不常用的东西,例如带有标题栏的许多控件,等等。这样的好处是很方便我们的编程,减少不必需的工作量。
6:WM_PAINT消息是一个很特殊,比较复杂的消息,它不是由程序员来发送的,而是由系统在消息队列为空的时候,系统会检查一个叫做UpdateRect的区域,当这个区域不为NULL的时候,系统会自动发送一个WM_PAINT消息。详细的可以参照我的一另外一篇文章。
7:BeginPaint,EndPaint,这两个函数只能用在,也必须用在WM_PAINT的消息处理函数中。为什么呢?简单的说明下:
由于WM_PAINT的消息的特殊性,它是在系统在消息队列为空的时候,检查UpdateRect区域是否为空,当不为空的时候,就会发送一个WM_PAINT消息。当时请注意,WM_PAINT并不自动来清除这个UpdateRect区域,也就是说,如果我我们不清除这个UpdateRect区域,系统就会源源不断的发送WM_PAINT消息过来,这个不是我们希望看见得,为了处理这种问题,所以我们需要在我们处理完WM_PAINT消息结束后,设置UpdateRect为空,保持一个正常的消息流通。
这个时候我们就是需要BeginPaint函数了。这个函数首先是为绘制准备所需要的HDC,其次是准备一个结构信息 PAINTSTRUCT ,它的结构如下:
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;
前三个参数是我们所关心的,后面三个我们不需要管。
- hdc
- Handle to the display DC to be used for painting.
- fErase
- Specifies whether the background must be erased. This value is nonzero if the application should erase the background. The application is responsible for erasing the background if a window class is created without a background brush. For more information, see the description of the hbrBackground member of the WNDCLASS structure.
- rcPaint
- Specifies a RECT structure that specifies the upper left and lower right corners of the rectangle in which the painting is requested, in device units relative to the upper-left corner of the client area.
- 8 WM_CLOSE,WM_QUIT,WM_DESTROY: 这三个消息比较让人晕的消息,baidu 了一下,发现如下的了解: 一般我们是发送WM_CLOSE 消息,DefWindowProc 默认的是调用DestroyWindow(),这个函数又发送WM_DESTROY, 在WM_DESTROY 的响应函数里面,调用 PostQuitMessage(0);, 这个函数会给系统发送WM_QUIT 消息,这样在GetMessage 返回值为0 ,消息循环终止,程序结束。