沧桑不尽
无穷的沧桑,不尽的落叶

在来啰嗦之前,希望大家能够做好准备,这一节知识有点多,内容有点长。但愿大家能够一口气读完,如果一口气读不完,那就换口气接着读。

 

      上节中我们用MessageBox()就实现了一个真正的窗口。MessageBox()中的原型如下:


Int MessageBox(HWND hWnd,
                    LPCTSTR lpText,
                    LPCTSTR lpCaption,
                    UINT        uType);

参数解释

hWnd 所属对话框所属窗口的句柄,如果是NULL,则此对话框不属于任何一个窗口。

lpText 对话框窗口的显示内容。

lpCaption 对话框窗口的标题。

uType 对话框的样式和动作(像是确定按钮,还是取消按钮就是设置这里的)

 

关于这个函数的细节可以看这里

http://msdn.microsoft.com/en-us/library/ms645505(VS.85).aspx

 

       到此为止,你也算是会了窗口程序的编写,但只是一个开始,不过这已经很好,可能会让你感觉到了C的魅力,也可能会稍微解点C语言能干什么的疑惑。在开始写代码之前,我有必要把细节和原理先说明下。

Windows下一个窗口创建的过程有以下几个步骤:

 

1.        程序创建一个窗口,首先要向Windows系统注册一个窗口类wndclassex,其实就是定义一个变量,变量的类型是WNDCLASSEX(结构体)。该结构体的定义与介绍看这里(http://msdn.microsoft.com/en-us/library/ms633577(VS.85).aspx)


Code
成员介绍
         cbSize 值为sizeof(WNDCLASSEX),在调用GetClassInfoEx前必须要先设置它值。
         

style 窗口类的样式,它的值可以是窗口样式值的任意组合。

           可以有以下的值

lpfnWndProc 指向窗口处理函数(回调函数)。处理窗口事件,像单击鼠标会怎样,右击鼠标会怎样,都是由此函数控制的。

cbClsExtra 为窗口类的额外信息做记录,系统初始化为0
cbWndExtra
记录窗口实例的额外信息,系统初始为0.如果程序使用WNDCLASSEX注册一个从资源文件里创建的对话框,则此参数必须设置为DLGWINDOWEXTRA

hIcon 窗口类的图标,为资源句柄,如果设置为NULL,系统将为窗口提供一个默认的图标。

hCursor 窗口类的鼠标样式,为鼠标样式资源的句柄,如果设置为NULL,系统提供一个默认的鼠标样式。

hbrBackground 窗口类的背景刷,为背景刷句柄,也可以为系统颜色值,如果颜色值已给出,则必须转化为以下的HBRUSH的值

·       COLOR_ACTIVEBORDER

·       COLOR_ACTIVECAPTION

·       COLOR_APPWORKSPACE

·       COLOR_BACKGROUND

·       COLOR_BTNFACE

·       COLOR_BTNSHADOW

·       COLOR_BTNTEXT

·       COLOR_CAPTIONTEXT

·       COLOR_GRAYTEXT

·       COLOR_HIGHLIGHT

·       COLOR_HIGHLIGHTTEXT

·       COLOR_INACTIVEBORDER

·       COLOR_INACTIVECAPTION

·       COLOR_MENU

·       COLOR_MENUTEXT

·       COLOR_SCROLLBAR

·       COLOR_WINDOW

·       COLOR_WINDOWFRAME

·       COLOR_WINDOWTEXT

lpszMenuName 指向一个以NULL结尾的字符床,同目录资源的名字一样。如果使用整型id表示菜单,可以用MAKEINTRESOURCE定义一个宏。如果它的值为NULL,那么该类创建的窗口将都没有默认的菜单。

lpszClassName 窗口类的名字,字符串类型。

hIconSm 小图标的句柄,在任务栏显示的图标,可以和上面的那个一样。

 

定义一个WNDCLASSEX类型变量后,在给变量成员初始化后,我们就可以用
RegisterWindowEx(&wndclassex)
来注册这个窗口类了。

 

这个注册过程,就和我们平常创建一个项目一样,都要先注册才能创建

 

 

 

2.        创建窗口

这一步很简单,就是利用CreateWindowEx()函数来创建就是了。

CreateWindowEx函数的原型如下:


Code
参数说明
                 dwExStyle:指定窗口的扩展风格。该参数可以是下列值:

                      WS_EX_ACCEPTFILES:指定以该风格创建的窗口接受一个拖拽文件。

                  WS_EX_APPWINDOW:当窗口可见时,将一个顶层窗口放置到任务条上。

                  WS_EX_CLIENTEDGE:指定窗口有一个带阴影的边界。

                          WS_EX_CONTEXTHELP:在窗口的标题条包含一个问号标志。

                      WS_EX_CONTROLPARENT:允许用户使用Tab键在窗口的子窗口间搜索。

                  WS_EX_DLGMODALFRAME:创建一个带双边的窗口;该窗口可以在dwStyle中指定WS_CAPTION风格来创建一个标题栏。

                  WS_EX_LEFT:窗口具有左对齐属性,这是缺省设置的。

                  WS_EX_LEFTSCROLLBAR:如果外壳语言是如HebrewArabic,或其他支持reading order alignment的语言,则标题条(如果存在)则在客户区的左部分。若是其他语言,在该风格被忽略并且不作为错误处理。

                  WS_EX_LTRREADING:窗口文本以LEFTRIGHT(自左向右)属性的顺序显示。这是缺省设置的。

                  WS_EX_MDICHILD:创建一个MD子窗口。

                    WS_EX_NOPATARENTNOTIFY:指明以这个风格创建的窗口在被创建和销毁时不向父窗口发送WM_PARENTNOTFY消息。

WS_EX_OVERLAPPEDWS_EX_CLIENTEDGEWS_EX_WINDOWEDGE的组合。

                        WS_EX_PALETTEWINDOWWS_EX_WINDOWEDGE, WS_EX_TOOLWINDOWWS_WX_TOPMOST风格的组合WS_EX_RIGHT:窗口具有普通的右对齐属性,这依赖于窗口类。

WS_EX_RIGHTSCROLLBAR:垂直滚动条在窗口的右边界。这是缺省设置的。

                    WS_EX_RTLREADING:如果外壳语言是如HebrewArabic,或其他支持读顺序对齐(reading order alignment)的语言,则窗口文本是一自左向右)RIGHTLEFT顺序的读出顺序。

WS_EX_STATICEDGE:为不接受用户输入的项创建一个3一维边界风格

                      WS_EX_TOOLWIDOW:创建工具窗口,即窗口是一个游动的工具条。

WS_EX_TOPMOST:指明以该风格创建的窗口应放置在所有非最高层窗口的上面并且停留在其L,即使窗口未被激活。使用函数SetWindowPos来设置和移去这个风格。

                  WS_EX_TRANSPARENT:指定以这个风格创建的窗口在窗口下的同属窗口已重画时,该窗口才可以重画。

  由于其下的同属富日已被重画,该窗口是透明的。

 

IpClassName: 窗口类的名字。

lpWindowName:指向一个指定窗口名的空结束的字符串指针。其实就是窗口的名字。

dwStyle:指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格。

x:窗口的横坐标。

y:窗口的竖坐标。

nWidth:窗口的宽度。

nHeight:窗口的高度。

hMenu:菜单句柄,或依据窗口风格指明一个子窗口标识。

hlnstance:与窗口相关联的模块事例的句柄。

lpParam:指向一个值的指针,该值传递给窗口 WM_CREATE消息

返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。

 

 

3.        显示窗口

显示窗口就是更简单的事情了。

连个函数轻松搞定,第一个函数就是ShowWindow(),原型如下:

BOOL ShowWindow(      
            HWND hWnd,
//当前的窗口句柄
            int nCmdShow //可见状态
            );

因为CreateWindowEx函数创建的窗口是在内存中的,并没有显示到显示器上,用ShowWindow()函数,设定窗口的可见状态,并把数据从内存中移动到显卡上,以便显示。
         第二个函数就是UpdateWindow()

         函数原型:

 BOOL UpdateWindow(HWND hWnd);

 

 描述:

  这个 UpdateWindow 函数通过发送重绘消息 WM_PAINT 给目标窗体来更新目标窗体客户区的无效区域。如果那个窗体的无效区域没有,就不发送重绘消息 WM_PAINT 。注意了,这个 API 函数是直接发送消息 WM_PAINT 给目标窗体的,没有进入过消息队列。

  函数参数:

  hWnd 一个要更新的窗体的句柄

  函数返回值:

  如果函数调用成功,返回值为非零值。

如果函数调用不成功,返回值为零。
 
经过这三步后,一个窗口就实现了,就创建了出来,难不,也真够难的,Windows想的正周到,把创建过程的每一个细节都给想到了,每毫秒可能发生的事情都想到了,难怪Windows那么贵,还不开源。也算是人间的产品嘛,费的心血可真不少呀。说难其实也不难,创建一个窗口程序也就三步:一注册,二创建,三显示。很容易就ok了。这T他妈容易了吧。
 
原理就是这些的,我想我已经说的挺明白的了,如果你有什么疑惑,可以给我发邮件(cangsanbujin@126.com
下面我们就按照上面所说的来编程实现一个窗口:

Code

编译运行后,可以看到一个白色背景的窗口出来了。如下图

     

 哎,这一节,篇幅可是真有点长的,看完估计得换几口气吧,但是只要你看到了这些,你的水平就立马上了一个档次。想你看完后也许会头昏脑胀的,没有再看下去的信心的,但是估计当你把我的代码复制到VC中编译运行后,看到一个可爱的窗口时,肯定又会重新点燃你心中学习的热情吧,因为你已经看到了成功,看到了成就,一种成就感犹然自心中生,自信也提起来了,这比什么都好,人嘛就得对自己充满信心的。所以大家要发扬持之以恒的精神,坚持和我一起把这段苦闷的入门过程给走完,那么编程就不再是痛苦,而是一种乐趣。其实写这些程序很多东西都不用去记的想WNDCLASSEX结构的成员及成员作用,这些都不用去死记,只要知道有这么个东西,到时时再查就可以了,编程用到的函数、结构体那么多,谁想记呀。这一节已经留下了些问题,在下节介绍的,大家如果有余力的话,可以先查下资料的。

posted on 2009-08-06 08:38  沧桑不尽  阅读(7929)  评论(32编辑  收藏  举报