怀念从前~~ Ping MM:Request timed out; Ping money:estination unreachable; Ping Love:Unknown host name

第四章:Windows 图形界面

上一篇 / 下一篇  2008-05-11 23:54:30

第四章:Windows 图形界面

1.1 了解窗口

 

在图形化基于视窗的应用程序里,窗口就是屏幕上一块可视区域,应用程序的窗口包括标题栏,菜单栏,Windows系统菜单,最小化按钮,最大化按钮,恢复按钮,关闭按钮,可改变大小的边框,窗口客户区,垂直滚动条,水平滚动条.

窗口客户区是应用程序显示输出部分

 

1.2 窗口的创建

 

1.21 创建Win32工程和MessageBox函数

Windows 应用程序的主函数是:

int APIENTRY WinMain(HINSTANCE hInstance,      //应用程序的实例句柄

                                   HINSTANCE hPrevInstance,  //Win16留下的废物,不用参数

                                   LPSTR lpCmdLine,                   命令行参数

                                   int  nCmdShow)                //主窗口初始化的显示方式  

 

 

Windows 弹出对话框的函数是:

::MessageBox(HWND hwnd,    //一个窗口句柄,指定的对话框属于哪一个窗口所有

                                                        //设为NULL,表示没有窗口拥有该对话框

              LPCSTR lpText,   //对话框的正文

                       LPCSTR lpCaption,  //对话框的标题

                       UINT uType)      //对话框显示按钮种类和行为

nType 指示了对话框显示按钮的种类和行为,可以设成如下的值:

1:  MB_OK 确定按钮

2:  MB_OKCANCEL  包括两个按钮:确定和取消按钮

3:  MB_ABORTRETRYIGNORE  包括三个按钮:终止,调试和忽略

4:  MB_YESNOCANCEL  包括三个按钮:是,否和取消

5:  MB_YESNO     是和否按钮

6:  MB_RETRYCANCEL 重试和取消按钮

7:  MB_ICONHAND  一个停止标志图标

8:  MB_ICONQUESTION  一个询问标志图标

9:  MB_ICONEXCLAMATION 一个感叹号图标

10: MB_DEFBUTTON1  第一个按钮是选中按钮

11: MB_DEFBUTTON2  第二个按钮是选中按钮

12: MB_DEFBUTTON3  第三个按钮是选中按钮

13: MB_DEFBUTTON4  第四个按钮是选中按钮

MessageBox 函数返回被选中按钮的ID号,ID号为一个整形数值,这个宏在WINUSER.H中定义:

ID号 = ID + 按钮单词

如果确定按钮被选中,将返回:IDOK

 

示例代码:

 

#include <windows.h>

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     int nSet = ::MessageBox(NULL,"Hello world","标题",MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON3);

     if(nSet == IDYES)

     {

         ::MessageBox(NULL,"用户选择了是按钮","标题",MB_OK);

     }

     else if(nSet == IDNO)

     {

         ::MessageBox(NULL,"用户选择了否按钮","标题",MB_OK);

     }

     else if(nSet == IDCANCEL)

     {

         ::MessageBox(NULL,"用户选择了取消按钮","标题",MB_OK);

     }

     return 0;

}

 

 

 

1.22 Windows 的消息驱动

创建窗口后,就要对窗口的行为负责,比如用户拖动窗口时,应跟随鼠标移动这个窗口.如果不这么做,程序将失去窗口界面的友好性,但是,如何知道用户在窗口上的动作呢

是操作系统告诉程序的,Windows不断向程序发送消息,通知用户在窗口上的动作

当 Windows向程序发送消息时,它调用程序中的一个函数,这个函数称为消息处理函数,它是一个自定义的回调函数,原形如下:

LRESULT CALLBACK WinProc(HWND hwnd,  //窗口句柄

UINT message, //消息ID号

WPARAM wParam, //消息参数,其值取决于消息//的类型

LPARAM lParam) //消息参数,其值取决于消息

//的类型

 

例如,一般的应程序接受到 WM_CLOSE 消息时会试图销毁自己的窗口,下面代码为了关闭了记事本程序,向它的主窗口发送了 WM_CLOSE 消息,运行这个程序之前请先新建一个文本文档,然后再打开这个文本文档.

 

#include <windows.h>

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     HWND hwnd;

     BOOL bStart = FALSE;

     while(bStart == FALSE)

     {

         //查找标题为"新建文本文档.txt - 记事本"的窗口

         hwnd = ::FindWindow("Notepad","新建文本文档.txt - 记事本");

         if(hwnd != NULL)

         {

              //向窗口发送WM_CLOSE 消息

              ::SendMessage(hwnd,WM_CLOSE,0,0);

              ::MessageBox(NULL,"新建文本文档.txt - 记事本窗口已关闭","消息提示",MB_OK);

              bStart = TRUE;

         }

         else

         {

              ::MessageBox(NULL,"请先启动新建文本文档.txt - 记事本窗口","消息提示",MB_OK);  

         }

     }

     return 0;

}

 

以上是一个应用程序向另一个应用程序发送窗口的过程,系统向应用程序发送消息的过程是类似的,系统为应用程序传递所有输入到它的各个窗口,每个窗口都关联一个消息处理函数,消息处理函数处理输入,然后再将控制权交给系统

 

1.2.3 创建第一个窗口.

下面是一个最简单的窗口程序源代码,它的作用是弹出一个典型的 Windows 程序窗口,这些代码可以做为今后用 API 写 Windows 程序的基本框架

#include <windows.h>

 

//消息处理函数原形

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     char *szClassName = "WndClass";

     WNDCLASSEX wndclass;

     //用描述主窗口的参数填充WNDCLASSEX 结构

     wndclass.cbSize = sizeof(wndclass);  //定义结构的大小

     wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  //定义窗口样式

     wndclass.lpfnWndProc = WndProc;  //指定本窗口的消息处理函数

     wndclass.cbClsExtra = 0;    //没有额外的类内存

     wndclass.cbWndExtra = 0;   //没有额外的窗口内存

     wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);   //使用默认的图标

     wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);     //使用默认的光标

     wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);  //定义窗口的背景颜色为灰色

     wndclass.hInstance = hInstance;  //实例句柄

     wndclass.lpszClassName = szClassName;   //窗口类名称

     wndclass.lpszMenuName = NULL;    //不使用菜单

     wndclass.hIconSm = NULL;   //没有类的小图标

 

     //注册窗口类

     ::RegisterClassEx(&wndclass);

 

     //创建主窗口

     HWND hwnd = ::CreateWindowEx(0,  //不定义扩展样式

                                     szClassName,  //类名

                                     "Hello world",  //窗口标题

                                     WS_OVERLAPPEDWINDOW,  //窗口风格

                                     CW_USEDEFAULT,   //默认的窗口X 轴坐标

                                     CW_USEDEFAULT,   //默认的窗口Y 轴坐标

                                     CW_USEDEFAULT,   //默认的窗口宽度

                                     CW_USEDEFAULT,   //默认的窗口高度

                                     NULL,   //没有父窗口句柄

                                     NULL,   //没有菜单句柄

                                     hInstance,  //程序实例句柄

                                     NULL);     //没有用户数据

 

     if(hwnd == NULL)

     {

         ::MessageBox(NULL,"创建窗口出错","error",MB_ICONHAND);

         return -1;

     }

 

     //显示窗口

     ::ShowWindow(hwnd,nCmdShow);

 

     //刷新窗口客户区

     ::UpdateWindow(hwnd);

 

     //从消息队列中取出消息,交给消息处理函数处理,直到GetMessage 函数返回FALSE ,结束消息循环

     MSG msg;

     while(::GetMessage(&msg,NULL,0,0))

     {

         //转化键盘消息

         ::TranslateMessage(&msg);

 

         //将消息发送给消息处理函数

         ::DispatchMessage(&msg);

     }

 

     return msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)

{

     char *szText = "My first window process ";

     HDC hdc;  //声明设备环境句柄

     PAINTSTRUCT ps;

     switch(msg)

     {

     case WM_PAINT:  //窗口客户区需要重画

         {

              //使无效的客户区变得有效,并取得设备环境句柄

              hdc = ::BeginPaint(hwnd,&ps);

              ::TextOut(hdc,0,0,szText,strlen(szText));

              ::EndPaint(hwnd,&ps);

              return 0;

         }

     case WM_DESTROY:  //正在销毁窗口

         {

              //向消息队列投递一个WM_QUIT 消息,促使GetMessage 函数返回0,结束消息循环

              ::PostQuitMessage(0);

              return 0;

         }

     }

 

     // 将我们不处理的消息交给系统做默认处理

     return ::DefWindowProc(hwnd,msg,wParam,lParam);

}

分析以上程序,可以得出在桌面上创建一个窗口的具体步骤

(1)    注册窗口类(RegisterClassEx)

(2)    创建窗口(CeateWindowEx)

(3)    在桌面上显示窗口(ShowWindow)

(4)    更新窗口客户区(UpdateWindow)

(5)    进入无限的消息获取和处理消息的循环,首先是获取消息(GetMessage),如果有消息到达,则通过 DispatchMessage 函数将消息发送到指定的消息处理函数 WndProc;

 

 

创建窗口的知识要点:

(1).指定窗口类的样式:

wndclass.style = CS_HREDRAW | CS_VREDRAW;

这句代码指定了如果窗口宽度或高度改变了就重画整个窗口,在 WINUSER.H 中定义了窗口类的全部可用样式,可以组合使用各种样式

(2)指定窗口客户区重画时使用的画刷

wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);

这句代码指定使用 windows 预定义的白色背景画刷,也可以自己创建一个画刷对象以便指定喜欢的颜色为窗口背景色,下面的代码将窗口的背景色改为了黄色

Wndclass.hbrBackground = (HBRUSH)::GetSolidBrush(RGB(255,255,0));

…………………

………………….

::DeleteObject(wndclass.hbrBackground);  //最后别忘记在程序结束之前删除创建的刷子释放资源

(3)指定窗口的风格

CreateWindows 第四个参数指定了窗口的风格,下面列出了一些最常见的风格定义,它们是以 WS 为前辍的预定义的值

WS_BORDER  创建一个单边框的窗口

WS_CAPTION  创建一个有标题框的窗口(包括WS_BORDER风格)

WS_CHILD   创建一个子窗口,这个风格不能与 WS_POPVP 风格合用

WS_DISABLED  创建一个初始状态为禁止的子窗口,一个禁止状态的窗口不能接受来自用户的输入信息

WS_DLGFRAME. 创建一个带对话框边框风格的窗口,这种风格的窗口不能带有标题条

WS_HSCROLL   创建一个有水平滚动条的窗口

WS_VSCROOL  创建一个有垂直滚动条的窗口

WS_ICONIC    创建一个初始状态为最小化的窗口,与 WS_MINIMIZE 风格相同

WS_MAXIMIZE  创建一个初始状态为最大化的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格

WS_OVERLAPPED  产生一个层叠窗口,一个层叠的窗口有一个标题条和一个边框,与 WS_TILED 风格相同

WS_OVERLAPPEDWINDOW 创建一个具有 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,WS_THICKFRAME, WS_MINIMIZEBOX,WS_MAXMIZEBOX 风格的层叠窗口

WS_POPUP 创建一个弹出式窗口,该风格不能与WS_CHLD 风格同时使用

WS_POPUPWINDOW 创建一个具有 WS_BORDER, WS_POPUP, WS_SYSMENU, 风格的窗口,WS_CAPTION 和 WS_POPUPWINDOW 必须同时使用才能使窗口可见

WS_SIZEBOX 创建一个可调边框的窗口,与 WS_THICKFRAME. 风格相同

WS_SYSMENU 创建一个在标题条上带有窗口菜单的窗口,必须同时设定 WS_CAPTION 风格

 

WS_THICKFRAME. 创建一个具有可调边框的窗口,与 WS_SIZEBOX 风格相同

WS_VISBLE 创建一个初始状态为可见的窗口

 

(4)消息队列 MSG 结构

Windows 为每个线程维护了一个消息队列,每当有消息进入时,Windows 就利用GetMessage 函数调用线程的消息队列来填充 MSG 结构,这个结构定义了消息的所有属性

Typedef struct tagMSG

{

       HWND hwnd;    //消息要发往的窗口句柄

       UINT message;   //消息标识符,以WM_开头的预定义值

       WPARAM wParam;  //消息参数之一

       LPARAM lParam;    //消息参数之二

       DWORD time;       //消息放入消息队列的时间

       POINT pt;    //这是一个POINT 数据结构,表示消息放入消息队列时的鼠标位置

}MSG,  &PMSG;v


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-07-06  
  12345
6789101112
13141516171819
20212223242526
2728293031  

数据统计

  • 访问量: 9644
  • 日志数: 224
  • 图片数: 2
  • 商品数: 3
  • 文件数: 1
  • 影音数: 1
  • 建立时间: 2007-06-19
  • 更新时间: 2008-06-15

RSS订阅

Open Toolbar