
常用软件类: |
|杀毒安全 | |联络聊天 | |网络软件 | |多媒体类 | |系统工具 | |图形图像 | |系统工具 | |应用软件 | |行业软件 |
开发设计类: |
|动画制作 | |图像处理 | |3D设计 | |操作系统 | |站长学院 | |网络相关 | |WEB设计 | |数据库类 | |程序开发 |
设计完窗口后我们要注册窗口类RegisterClass,注册完了才能生产这一款窗口,否则操作系统不知道你要产生什么样的窗口。
随后我们调用CreateWindow去产生窗口,这里有个窗口的样式参数,WS_OVERLAPPEDWINDOW是一个包装样式,如果想去掉某个功能就将去掉的样式取反,然后将结果与包装样式相与。WM_DISABLE是窗口不可用了。
如果我们没有ShowWindow则应用程序启动后看不见窗口,这时我们在代码里添加一个空格,然后删除空格,编译器发现代码发生改变会帮我们重新编译,这时报告一个fatal error,因为刚才的应用程序启动后没有关闭,新的就无法覆盖原来的,注意刚才没有窗口并不表示程序没有运行,窗口是窗口,程序是程序。窗口只是程序产生的一个小的部件。所以创建了窗口后我们要把内存中的窗口显示出来,不过如果在style属性里指定了ws_visible就不用ShowWindow了。书上经常有UpdateWindow,但我们这里可以不用。
有了窗口用户就可以干任何事情了,而我们就要对用户的这些操作进行处理,调用GetMessage来取消息。这里我们定义一个结构体:MSG来保存这些消息。GetMessage的第一个参数是一个MSG地址,如果不是地址的话无法返回值,我们就取不到消息。第二个参数是一个窗口的句柄,由于消息是跟一个窗口相关联的。如果我们把这个参数填为NULL,表示要取属于本应用程序的所有消息,包括该应用程序内所有窗口的消息。第三、四个参数是要取的消息的范围(消息是一个整数),这个参数可以帮助你过滤某些消息。我们处理完消息后又要来取消息又要处理,这样一个循环什么时候停止呢?当GetMessage取到WM_QUIT消息时就要会返回0,也只有这个消息能让GetMessage返回0,这样程序就能退出了。这里要注意的是:如果GetMessage的第二个参数填的是本窗口的句柄,则收不到WM_QUIT消息,这样程序就退不出去了,因为WM_QUIT是个特殊的消息,该消息不跟任何窗口相关联,属于应用程序的。所以我们第二个参数要填为NULL。
TranslateMessage是将WM_KEYDOWN和WM_KEYUP转换为WM_CHAR的函数,因为有时我们想对用户按下哪个键进行反应,所以我们只需要WM_CHAR来判断比较简单。当这三个消息同时存在的时候,先取WM_CHAR,再取WM_KEYDOWN,最后是WM_KEYUP。
DispatchMessage是分派、转发消息的函数。
至此我们的程序就差一个处理消息的函数了。lpfnWndProc需要填一个函数的指针,这个函数是回调函数:只要窗口收到消息了就去找这个规定好的回调函数去处理。就好象我们买了汽车后,在汽车的说明书上就指定了汽车的维修地点,当你的车坏了就去这些指定的地点去修。
介绍sprintf和MessageBox函数。
CALLBACK表示调用方式用Pascal(_stdcall如Delphi)的调用方式进行调用,否则就是按照C语言的调用方式(_cdecl)进行调用。这主要是解决一个程序通用的问题。
__stdcall与__cdecl是两种不同的函数调用习惯,定义了参数的传递顺序、堆栈清除等。关于它们的详细信息请参看msdn。由于除了那些可变参数的API函数外,其余的API函数都是__stdcall习惯。由于VC++程序默认的编译选项是__cdecl,所以在VC++中调用这些__stdcall习惯的API函数,必须在声明这些函数的原型时加上__stdcall修饰符,以便对该函数的调用使用__stdcall习惯。我们曾有这样的经验,在Delphi(默认的编译选项是__stdcall)中编写的dll中的函数,在VC++中被调用时,总是造成程序崩溃,在函数的原型声明中加上__stdcall修饰符,便解决了这个问题。回调函数也必须是__stdcall调用习惯,在这里是用CALLBACK来标识的,否则,在NT4.0环境,程序将崩溃,但win98和win2000却没有这种现象。
演示代码,包括响应画图和加载图标、默认的WINDOWS消息的处理。
在16位的系统中系统中只有一个消息队列,所以系统必须等待当前任务处理消息后才可以发送下一消息到相应程序,如果一个程序陷入死循环或是耗时操作时系统就会得不到控制权。这种多任务系统也就称为协同式的多任务系统。Windows3.X就是这种系统。
而32位的系统中每一运行的程序都会有一个消息队列,所以系统可以在多个消息队列中转换而不必等待当前程序完成消息处理就可以得到控制权。这种多任务系统就称为抢先式的多任务系统。Windows95/NT就是这种系统
注意:不要用API Reference里的WinMain函数的定义,因为LPWSTR lpCmdLine里的W表示宽字节,即两个字节,本来是没问题的,但由于我们用的是盗版,这里就出问题了。
16位操作系统和32位操作系统,它们的根本区别就是,16位操作系统一次只读出两个格子
的数据,32位操作系统则可读出4个格子也就是4个字节。因为每个字节为8位二进制数,4
个字节就是32位,所以叫做32位操作系统。从WIN98开始,所有的WINDOWS操作系统都完全
是32位的了(windows95不是纯32位的操作系统,因为了兼有令人满意的速度和与旧的16位程序的良好兼容性,其内核本身就是一个16位与32位的混合体)。而且从386开始,所有的CPU都是32位,这就是说CPU一次处理4个字节的数据。因此,在程序里你最好尽量把变量定义为长整形,因为32位的变量不管寻址还是计算都是最快的。除非你在使用286计算机,或者DOS操作系统。
#include <windows.h>
#include "resource.h"
#include <stdio.h>
int x,y;
LRESULT CALLBACK myproc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
case WM_CLOSE:
if(IDOK==MessageBox(hwnd,"你是真的要退出吗?","系统提示",MB_OKCANCEL|MB_ICONINFORMATION))
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
case WM_CHAR:
{
char buf[100];
sprintf(buf,"%d",wParam);
MessageBox(hwnd,buf,"show",MB_OK);
break;
}
case WM_MOUSEMOVE:
{//这里和上面的情况用大括号一是为了防止buf的重复定义,二是为解决类似int x=LOWORD(lParam);的定义编译器糊涂报错。
HDC hdc=GetDC(hwnd);
char buf[100];
sprintf(buf,"x=%d,y=%d",x,y);
SetTextColor(hdc,RGB(255,255,255));
TextOut(hdc,0,0,buf,strlen(buf));
//InvalidateRect(hwnd,NULL,true);
//PostMessage(hwnd,WM_PAINT,0,0);
//SendMessage(hwnd,WM_PAINT,0,0);
x=LOWORD(lParam);
y=HIWORD(lParam);
memset(buf,0,100);
sprintf(buf,"x=%d,y=%d",x,y);
SetTextColor(hdc,RGB(0,0,0));
TextOut(hdc,0,0,buf,strlen(buf));
ReleaseDC(hwnd,hdc);
break;
}
}
return 1;
}
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASS wndclass;
wndclass.cbClsExtra=NULL;
wndclass.cbWndExtra=NULL;
wndclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
//wndclass.hCursor=LoadCursor(NULL,IDC_HAND);
wndclass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_POINTER));
//wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
wndclass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=myproc;
wndclass.lpszClassName="mywnd";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW;
RegisterClass(&wndclass);
HWND hwnd=CreateWindow("mywnd","window test",WS_OVERLAPPEDWINDOW,100,100,400,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOW);
MSG msg;
while(GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 1;
}