zoukankan      html  css  js  c++  java
  • windows程序设计第三章Windows和消息

    A Windows of One's Own

    很简单,CreateWindow即可。等等,该函数的第一个参数怎么是window class name,这个窗口类又要有一个什么window procedure?

    Architectural概论

        windows(窗口)是个object(对象)。 child windows(control windows):push buttons,radio buttons,check boxes.....

    如何理解message呢,我们已经习惯调用操作系统的函数,但操作系统也可以调用应用程序的函数。当windows响应某一事件时,会通过调用相应的procedure代码,把message发送给程序。procedure代码要么是程序的一个函数,要么位于dll中。procedure根据消息完成一些操作,并将控制权交还给windows.

         窗口是基于窗口类创建的。后者规定了处理消息的窗口过程,可实例化多个窗口。 当windows程序运行时,Windows创建消息队列。有些消息存于队列,以待在windows的message loop中被抓取并dispatch,也有一些消息会直接送入窗口过程,而不进入消息队列。

    HELLOWIN程序

    #include <Windows.h>
    LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
    {
    	static TCHAR szAppName[] = TEXT("HelloWin");
    	HWND hwnd;
    	MSG msg;
    	WNDCLASS wndclass;
    
    	wndclass.style = CS_HREDRAW | CS_VREDRAW;
    	wndclass.lpfnWndProc = WndProc;
    	wndclass.cbClsExtra = 0;
    	wndclass.cbWndExtra = 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;
    	wndclass.lpszClassName = szAppName;
    
    	if (!RegisterClass(&wndclass))
    	{
    		MessageBox(NULL,TEXT("fail!"),szAppName,MB_ICONERROR);
    		return 0;
    	}
    
    	hwnd = CreateWindow(szAppName,
    						TEXT("The hello program"),
    						WS_OVERLAPPEDWINDOW,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						NULL,
    						NULL,
    						hInstance,
    						NULL						
    						);
    
    	ShowWindow(hwnd,iCmdShow);
    	UpdateWindow(hwnd);
    
    	while (GetMessage(&msg,NULL,0,0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return msg.wParam;
    
    //	return 0;
    }
    //WParam是int,LPARAM是long
    LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
    	HDC hdc;
    	PAINTSTRUCT ps;
    	RECT rect;
    
    	switch(message)
    	{
    	case WM_CREATE:
    		PlaySound(TEXT("D:\\Windows XP 启动.wav"),NULL,SND_FILENAME | SND_ASYNC);
    		return 0;
    	case WM_PAINT:
    		hdc = BeginPaint(hwnd,&ps);
    		GetClientRect(hwnd,&rect);
    		DrawText(hdc,TEXT("Hello,高峰"),-1,&rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    		EndPaint(hwnd,&ps);
    		return 0;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	}
    
    	return DefWindowProc(hwnd,message,wParam,lParam);
    }
    

    程序截图如下

    image

    客户区是指程序可draw的区域,通常位于边框和标题栏之间。

    Thinking Globally

    上面的windows基本框架以后可照搬。

    windows函数调用

    上面的程序包含了18个win函数调用,不解释先。

    大写的标识符

    其实都是些常数,其前缀有一定的意义,它们的定义都在头文件中可以查看。

    新的数据类型

    主要是MSG,WINDCLASS,PAINTSTRUCT和RECT

    获得各种Handle

    HINSTANCE, HWND, HDC(设备上下文的句柄),所谓句柄,就是一个和某一个对象联系起来的32位数字。依靠句柄,可在windows函数之间访问对象。

    匈牙利命名法

    变量名同时表征变量类型和变量意义。

    Registering 窗口类

    最重要的两个域为第二个lpfnWndProc和最后一个,前者指定窗口过程函数,后者指定窗口类名。

    创建窗口

    使用CreateWindow函数,返回hwnd(HWND类型,窗口句柄)

    显示窗口

    创建窗口后,窗口的信息位于内存,还没有显示在video display上。需调用ShowWindow将窗口在屏幕上显示。如ShowWindow的第二个参数为SW_SHOWNORMAL,则窗口的客户区将被擦拭。而调用UpdateWindow可导致客户区重绘(发送了WM_PAINT消息)。

    消息循环

    GetMessage函数抓取消息,除了抓取WM_QUIT消息会返回0终止循环之外,其他消息都返回非零数。

    TranslateMessage(&msg);将做一些键盘消息转换(详情见第六章)。DispatchMessage(&msg);将消息返回给windows,windows再将其发送给适当的窗口过程进行处理。这意味着是windows调用了窗口过程函数WndProc,当WndProc处理完后,将控制权交还给windows,即回到DispatchMessage调用后,接着继续消息循环。

    窗口过程

    每个窗口过程函数都对应于一个窗口类。窗口过程一般由windows调用,但程序中也可通过SendMessage间接调用程序中的窗口过程。

    处理消息

    在switch中没处理的消息,应调用DefWindowProc。

    播放声音文件

    WM_CREATE是在CreateWindow函数中被直接作为消息参数,调用了窗口过程。使用PlaySound时,异步播放,这样当声音响起后,即返回到调用方,以继续下面的初始化。

    WM_PAINT消息

          当客户区invalid必须要update时,将发送此消息。

          client区何时会invalid呢?当窗口初创时,整个client区都是invalid的,当调用UpdateWindow时,第一个WM_PAINT消息就这样产生了。当resize时,整个client区也会invalid,此时窗口过程也会收到WM_PAINT.当最小化后再次还原时,也会发送WM_PAINT。

         当窗口间互相重叠时,重叠部分被移开时,该部分invalid,也会发送WM_PAINT,但只重绘invalid部分。

         在BeginPaint中,如果client区背景还未擦掉,windows擦掉其背景。BeginPaint将使整个client区validated,它将返回一个device context的句柄,用以绘图。EndPaint用以释放DC句柄。

        GetClientRect中,left,top都是0,right,bottom反映客户区的长宽。

    WM_DESTROY消息

    用户点关闭按钮或点击系统菜单中的关闭命令时发送该消息。如果不在窗口过程中处理该消息,窗口是会被关掉,但程序没法终结。

    windows编程的麻烦

    几乎所有windows程序都在窗口过程中对消息做出响应,这是windows编程的大部分工作。在winMain中,不过就是窗口类注册,创建窗口,从消息队列取出并发送消息等事。

    Don’t call me ,i’ll call you

    在windows程序中,windows总是会调用你的程序,特别是窗口过程。

    Queued and Nonqueued Messages

    queued messages:放入消息队列。nonqueued消息,直接是windows调用某些函数的结果,并提供参数给WndProc的调用。

    Get In and Out Fast

    若处理某个消息耗时很长,20章有解决办法。

  • 相关阅读:
    arcsde 和oracle(双机热备)分布式安装(转载)
    ArcGIS Server分布式部署
    华为软件编程规范和范例(转载)
    常用Java开源库
    通过Word 2007发布Blog
    django中的models模块及数据库一些基本操作
    网页设计与后台程序解决方案模板引擎之Smarty
    Session 和 Cookie
    ul及li水平居中显示
    HTTP协议简介
  • 原文地址:https://www.cnblogs.com/speedmancs/p/1730877.html
Copyright © 2011-2022 走看看