`
lingzantia
  • 浏览: 150002 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

[翻译]-WinCE 程序设计 (3rd 版)--4.3 Windows控件

阅读更多

如果没有Windows控件库的话,编写Windows程序将会是一件缓慢而又艰苦的事情。并且,每个程序将会有自己的外观和反应。这会迫使用户对每种新的应用程序都要学习一套新的操作方式。幸运的是,通过操作系统提供的一系列控件,避免了上述情况的发生。简单的说,控件只不过是预先定义好的窗口类。每个类有一个Windows提供的特定的窗口过程,给这些控件提供预定义的用户和编程接口。

因为控件只是又一个窗口,所以可用CreateWindows或CreateWindowEx来创建窗口。控件是通过事件来通知父窗口的,而事件中包含WM_COMMAND消息,并且控件ID和句柄都编码在消息的参数中。

和所有的消息一样,WM_COMMAND含有wParam和lParam这两个通用参数。对一个WM_COMMAND消息来说,wParam的高字位含有通知码,用来说明发送该消息的原因。wParam的低字位含有发送该消息的控件的ID,通常在创建控件的时候定义该ID,为了更好的使用,应该保证ID在控件的所有兄弟窗口中是唯一的。lParam则包含了控件窗口的句柄。通常,通过控件ID来追踪WM_COMMAND消息来源比通过控件的窗口句柄来追踪要更容易一些,不过这两个信息都可以从该消息中获得。下面是典型的WM_COMMAND消息处理程序中的头几行代码:
case WM_COMMAND:
WORD idItem, wNotifyCode;
HWND hwndCtl;

// Parse the parameters.
idItem = (WORD) LOWORD (wParam);
wNotifyCode = (WORD) HIWORD(wParam);
hwndCtl = (HWND) lParam;

从这里可以看出,WM_COMMAND消息处理程序通常是用控件ID和通知码来判断WM_COMMAND消息发送的原因。

通过给控件发送预定义的消息,可以配置和操纵控件。除了这些事情,应用程序可以设置按钮的状态,给列表框增加或删除项,设置编辑框中选择的文本,所有这些都是通过给控件发送消息来完成的。控件通常是通过ID来标识的,但许多Window函数都要求用控件的句柄。这时可以用GetDlgItem函数来进行简单的转换。函数原型如下:
HWND GetDlgItem(HWND hDlg, int nIDDlgItem);
两个参数分别是控件的父窗口句柄和控件的ID。虽然从名字上看这个函数只能用在对话框上,但实际上它能用在任何窗口的控件上。关于对话框我将在第六章进行讨论。

另外一个很方便的函数是SendDlgItemMessage,用于给控件发送消息。该函数发送消息给指定ID的子窗口。函数原型如下:
LONG SendDlgItemMessage (HWND hParent, int nIDChild, UINT Msg, WPARAM wParam, LPARAM lParam);
这些参数和SendMessage中的很类似。实际上,下面的这段代码从功能上讲和SendDlgItemMessage是一样的。
LONG SendMessage (GetDlgItem (hParent, nIDChild), Msg, wParam, lParam);
唯一的不同在于方便性,SendMessage没有嵌入GetDlgItem而已。

下面是六个预定义的窗口控件类。它们是:
Button 各种按钮。
Edit 一种用于输入和显示文本的窗口。
List 一种包含字符串列表的窗口
Combo 编辑框和列表框的组合。
Static 显示用户不能编辑的文本或图片的窗口
Scroll bar 未和具体窗口进行绑定滚动条

每个控件都有很多函数,所以本章难以涉及全部。但我会快速浏览一下这些控件,对重要的函数也会提及的。后面还会为您展示一个示例程序--CtlView,用来演示这些控件及它们同父窗口之间的交互。

按钮控件
按钮控件允许有几种输入方式,并且有许多风格,包括下压按钮、复选框和单选框。每种风格都是为特定用途设计的,例如,下压按钮用来接收即时输入,复选框用于开/关(on/off)输入,单选框用于从多个选择中挑选一个。

下压按钮
下压按钮通常用于激发某种行为。当用户用手写笔按一个下压按钮,按钮会发送WM_COMMAND消息,其中wParam参数的高字位包含BN_CLICKED(用于按钮被单击的通知)通知码。

复选框
复选框包括一个正方形的框和一个标签,用来让用户指定选择。复选框会保持选择或未选择状态,直到用户点击它或者程序强制按钮改变状态。除了标准BS_CHECKBOX风格外,复选框还有一个三态风格BS_3STATE,允许按钮失效并显示为灰色。另两个风格BS_AUTOCHECKBOX和BS_AUTO3STATE,会自动更新控件的状态和外观来反映出选择或未选择以及三态复选框下的失效风格。

和下压按钮一样,当单击复选框时,它会发送BN_CLICKED通知。除非复选框具有前面说的自动风格,否则需要应用程序负责手工改变按钮的状态。通过给按钮发送BM_SETCHECK消息来设置按钮的状态,其中,把参数wParam设置为0来取消按钮选择,设置为1则是选择按钮。对于三态复选框,可以将BM_SETCHECK消息的wParam参数设置为2来表示按钮失效状态。通过BM_GETCHECK消息,应用程序可以判断当前按钮状态。

单选框
单选框允许用户从多个选项里进行选择。单选框将多个按钮集分组,每组集合里同时只有一个能被选中。如果使用的是标准风格BS_RADIOBUTTON,则需要由应用程序负责选中或取消选中单选框,来保证同时只有一个被选中。当然,和复选框一样,单选框有一个BS_AUTORADIONBUTTON风格,用来自动维护按钮组的状态,来保证只有一个被选择。

分组框
您可能会奇怪,分组框也是一种按钮。分组框看起来象一个带有文本标签的中空的框,包围着被分成一组的控件集。分组框只是用于分组,除了其上的标题文字外,没有其它编程的接口,该标题文字是在创建分组框的时候作为其窗口标题文字而指定的。应该在创建分组框内的控件后创建分组框。这可以保证分组框在Z坐标上低于其内的控件。

在Windows CE设备上使用分组框应该小心。问题不在于分组框自身,而在于Windows CE较小的屏幕。分组框占用了颇有价值的屏幕,而这本应该可以被功能控件更好的使用的。尤其是在具有非常小的屏幕的Pocket PC上会出现这种情况。在许多情况下,在控件集之间绘制一条线就可以明显将控件分组了,这和使用分组框的效果一样。

定制按钮外观
通过使用许多附加风格,您可以进一步定制目前提到的按钮的外观。风格BS_RIGHT,BS_LEFT,BS_BOTTOM和BS_TOP允许您指定按钮文本的位置,而不是使用默认在按钮上居中的风格。BS_MULTILINE风格允许您在按钮上指定多行文本。文字会自动调整来适合按钮的。按钮文字中的换行符(\n)可以用来具体指定从哪里换行。Windows CE并不支持BS_ICON和BS_BITMAP按钮风格。

自绘制按钮
通过指定BS_OWNERDRAW风格,您可以完全控制按钮的外观。当按钮被指定为自绘制风格,则由拥有按钮的窗口负责绘制按钮可能出现的所有状态。当窗口包含有自绘制按钮时,会收到一个WM_DRAWITME消息,用来通知窗口有一个按钮需要绘制。对于该消息,wParam参数包含有按钮ID,lParam则指向一个DRAWITEMSTRUCT结构,该结构定义如下:
typedef struct tagDRAWITEMSTRUCT
{
UINT CtlType;
UINT CtlID;
UINT itemID;
UINT itemAction;
UINT itemState;
HWND hwndItem;
HDC hDC;
RECT rcItem;
DWORD itemData;
} DRAWITEMSTRUCT;
CtlType设置为ODT_BUTTON(自绘制按钮),CtlID则和wParam一样,包含有按钮ID。itemAction包含标志位,指出需要绘制什么和为什么绘制。这些域中最重要的是itemState,它包含了按钮选择、失效等状态。hDC包含了按钮窗口的设备描述表句柄,rcItem则包含了按钮的尺寸。对自绘制按钮来说,itemDate应该设置为NULL。

正如您所期望的,WM_DRAWITEM处理程序中包含有许多GDI函数,用来绘制线条、矩形以及绘制按钮所需要的一切。绘制按钮的一个重要方面是要和系统中其它窗口的标准颜色匹配。因为这些颜色是可变的,所以不能硬编码到程序里。您可以通过GetSysColor函数来查询出合适的颜色。函数原型如下:DWORD GetSysColor(int nIndex);
该函数返回的是为系统中窗口和控件的不同外观而定义的颜色的RGB值。在众多作为参数的预定义索引值中,COLOR_BTNFACE返回的是按钮的表面颜色,COLOR_BTNSHADOW返回的是用于创建三维按钮的暗色。

编辑框
编辑框是一种允许用户输入和编辑文本的窗口。正如您所猜想的,编辑框是Windows控件库中最方便的控件之一。编辑框具有完整的编辑功能,包括与系统剪切板交互来剪切、复制和粘贴等,而这些都不需要应用程序协助。编辑框可以显示单行文本,或者当指定EX_MULTILINE风格时,显示多行文本。桌面版Windows中提供的记事本就是一个包含多行编辑框的顶层窗口。

编辑框有一些其它特性需要提一下。具有ES_PASSWORD风格的编辑框默认将输入的每个字符显示为星号(*)。控件保存了真正的字符。ES_READONLY风格则保护控件里的文本只能读和复制,但不能被修改。ES_LOWERCASE和ES_UPPERCASE风格则把输入的字符强制转换为对应的大小写。

通过WM_SETTEXT消息可以给编辑框添加文本,通过WM_GETTEXT消息可以检索文本。通过EM_SETSEL消息可以控制文本选择。该消息指定选择区域的起始字符和终止字符。其它消息允许查询和设置光标(指出在编辑域里的当前入口点)的位置。多行编辑框包含许多其它消息,比如控制滚动、按行列位置访问字符等。

列表框控件
列表框控件显示一个文本项列表,用户可以从中选择一个或多个项。列表框可以存储文本,还可以对列表项排序,管理列表项的显示,包括滚动显示等。通过设置列表框,可以允许单选、多选或者禁止选择列表项。

通过给列表框发送LB_ADDSTRING或LB_INSERTSTRING消息,传递指向字符串的指针到lParam参数里,就可以增加列表项。LB_ADDSTRING消息会把新添加的字符串放到列表项的尾部,而LB_INSERTSTRING可以把字符串放到列表项的任何位置。使用LB_FIND消息可以在列表框中搜索特定的项。

使用LB_GETCURSEL可以查询单选列表框的选择状态。对于多选框,使用LB_GETSELCOUNT和LB_GETSELITEMS来检索当前选择的项。使用LB_SETCURSEL和LB_SETSEL消息,可以用编程的方式来选择列表框里的项。

除了不支持自绘制列表框以及LB_DIR消息族,Windows CE支持大部分其它版本Windows所支持的列表框功能。Windows CE支持一种新风格LBS_EX_CONSTRINGDATA。具有这种风格的列表框不保存传给它的字符串,而是保存指向字符串的指针,并且由应用程序负责维护字符串。对于可能从资源文件中装载大型字符串数组的情况,使用这种处理方式可以节省内存,因为列表框不用维护一个字符串列表的单独副本。

组合框
组合框(如名字所暗示的)是控件的组合,也就是一个单行编辑框控件和列表框的组合。在从多个选项列表中选择一项或者为预定义的建议输入值提供编辑功能时,组合框是很节省空间的。在Windows CE下,组合框具有两种风格:下拉方式和下拉列表方式。(简化方式的组合框并不支持。)下拉风格的组合框包括一个编辑区域和一个位于右端的按钮。点击按钮会显示一个列表框,包含了更多选项。在选项上选择一个,会用选择的内容填写组合框的编辑域。下拉列表风格的组合框使用静态文本控件替代了编辑框。这允许用户从列表中选择一项,并防止用户输入不在列表中的项。

因为组合框组合了编辑控件和列表框控件,所以组合框的消息列表就像是这两个基本控件的消息组合。CB_ADDSTRING,CB_INSERTSTRING和CB_FINDSTRING的效果和列表框里中的同类消息类似。同样地,对下拉风格或下拉列表风格的组合框使用CB_SETEDITSELECT和CB_GETEDITSELECT消息,可以设置和查询编辑框里被选择的字符。而要控制下拉风格或下拉列表风格的组合框的下拉状态,可以使用CB_SHOWDROPDOWN和CB_GETDROPPEDSTATE消息。

和列表框的情况一样,Windows CE不支持自绘制组合框。但是组合框支持扩展风格--CBS_EX_CONSTSTRINGDATA,具有这种风格的组合框不保存列表项字符串,而是保存指向字符串的指针。和具有LBS_EX_CONSTSTRINGDATA风格的列表框一样,当应用程序有存储在ROM里的大型字符串数组时,这种处理方式可以节省内存,因为组合框不用维护字符串列表的单独副本。

静态控件
静态控件是显示文本、图标或者位图的窗口,不具有用户交互性。可以使用静态文本控件来标记窗口中的其它控件。静态文本控件显示的效果是由文本和控件风格来决定的。在Windows CE下,静态控件支持以下几种风格:
SS_LEFT 文本左对齐显示。如果需要,文本会折行来适应控件大小。
SS_CENTER 将文本在控件中间显示。如果需要,文本会折行来适应控件大小。
SS_RIGHT 文本右对齐显示。如果需要,文本会折行来适应控件大小。
SS_LEFTNOWORDWRAP 文本左对齐显示。文本不会折成多行显示,任何超出控件右边界的文本都会被裁剪掉。
SS_BITMAP 显示一个位图。控件的窗口文字指定了包含位图的资源的名字。
SS_ICON 显示一个位图。控件的窗口文字指定了包含图标的资源的名字。

具有SS_NOTIFY风格的静态控件在被点击、有效或失效的时候,会发送WM_COMMAND消息,但是Windows CE版的静态控件在双击的时候不会发送通知消息。SS_CENTERIMAGE风格在和SS_BITMAP或SS_ICON一起使用的时候,会使图片在控件上居中显示。SS_NOPREFIX风格可以和文本风格一起组合使用。能够避免将&符号解释为转义符号,防止把下个字符解释成加速字符。

Windows CE不支持具有SS_WHITEFRAME或SS_BLACKRECT风格的显示成填充矩形或中空矩形的静态控件;也不支持自绘制静态控件。

滚动条控件
滚动条控件是一个与其它控件有些不同的家伙。通常滚动条是绑定在窗口的侧边,用来控制窗口里数据的显示的。实际上,诸如编辑框和列表框等窗口控件都内部使用了滚动条控件。正是因为这种和父窗口的紧密关系,使得滚动条的接口与其它控件的有所不同。

滚动条使用WM_VSCROLL和WM_HSCROLL消息而不是WM_COMMAND消息来报告行为。垂直滚动条会发送WM_VSCROLL消息,水平滚动条会发送WM_HSCROLL消息。另外,不使用SB_SETPOSITION消息来设置滚动条的位置,而是有专用的函数来完成。下面来看一下这个独特的接口。

滚动条消息
一旦用户点击垂直滚动条来改变其位置的时候,WM_VSCROLL消息会发送到垂直滚动条的拥有者上。WM_HSCROLL则是当用户点击水平滚动条的时候发送到其拥有者上的。对这两个消息来说,wParam和lParam参数是一样的。wParam的低字位包含的代码指出为什么会发送该消息。图4-1显示了水平和垂直滚动条以及如何在滚动条不同位置点击来产生不同的消息。wParam的高字位包含滑块的位置,但仅仅在您处理SB_THUMBPOSITION和SB_THUMBTRACK代码(后面将简单介绍它们)时,这个值才是有效的。如果发送消息的滚动条是独立的没有绑定到窗口的控件,那么lParam参数则包含有滚动条的窗口句柄。

图4-1(略):滚动条和其热点。
滚动条发送的消息代码允许程序对滚动条支持的所有用户行为作出响应。表4-1列出了每个代码对应的行为。
表4-1:滚动代码

Codes

Response

For WM_VSCROLL

For WM_HSCROLL

For both WM_VSCROLL and WM_HSCROLL

SB_LINEUP

Program should scroll the screen up one line.

SB_LINEDOWN

Program should scroll the screen down one line.

SB_PAGEUP

Program should scroll the screen up one screen's worth of data.

SB_PAGEDOWN

Program should scroll the screen down one screen's worth of data.

SB_LINELEFT

Program should scroll the screen left one character.

SB_LINERIGHT

Program should scroll the screen right one character.

SB_PAGELEFT

Program should scroll the screen left one screen's worth of data.

SB_PAGERIGHT

Program should scroll the screen right one screen's worth of data.

SB_THUMBTRACK

Programs with enough speed to keep up should update the display with the new scroll position.

SB_THUMBPOSITION

Programs that can't update the display fast enough to keep up with the SB_THUMBTRACK message should update the display with the new scroll position.

SB_ENDSCROLL

This code indicates that the scroll bar has completed the scroll event. No action is required by the program.

SB_TOP

Program should set the display to the top or left end of the data.

SB_BOTTOM

Program should set the display to the bottom or right end of the data.


SB_LINExxx和SB_PAGExxx代码是相当易懂的。每次您可以将滚动位置移动一行或者一页。SB_THUMBPOSITION和SB_THUMBTRACK可以用两种方式之一来处理。当用户拖动滚动条滑块时,滚动条会发送SB_THUMBTRACK代码,这样程序可以交互地跟踪滑块的拖动。如果您的应用程序足够快,您就可以只处理SB_THUMBTRACK代码并交互的更新显示。如果您填写了SB_THUMBTRACK代码,但是您的应用程序必须快到足以重绘显示,这样滑块在拖动过程中不会出现停顿。在运行Windows CE的较慢设备上,这会是一个问题。

如果您的应用程序(或者操作系统)太慢,不能为每个SB_THUMBTRACK代码进行快速更新显示,您可以忽略掉SB_THUMBTRACK,并等待在用户拖动滚动条滑块时发出的SB_THUMBPOSITION代码。这样在用户移动完滑块后,您只需要更新显示一次即可。

配置滚动条
要使用滚动条,应用程序首先应该设置滚动范围的最小值和最大值以及初始位置。和桌面系统里的滚动条一样,Windows CE滚动条支持按比例调整滑块大小,这可以给用户提供反馈,了解当前看到的页占整个滚动范围的比例。要设置这些参数,Windows CE应用程序可以使用SetScrollInfo函数,其原型如下:
int SetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);

第一个参数可以是包含滚动条的窗口的句柄,也可以是滚动条自身的窗口句柄。第二个参数fnBar是一个标志位,用于判断窗口句柄的用法。该标志位可以是下面三个值之一:SB_HORZ用于窗口中标准水平滚动条;SB_VERT用于窗口中标准垂直滚动条;SB_CTL用于独立的滚动条控件。除非滚动条是控件,否则窗口句柄是包含滚动条的窗口的句柄。在句柄是滚动条控件自身的句柄时,使用SB_CTL。最后一个参数时fRedDraw,一个布尔值,指出是否在调用完成后重新绘制滚动条。第三个参数是指向SCROLLINFO结构的指针,该结构定义如下:
typedef struct tagSCROLLINFO
{
UINT cbSize;
UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
} SCROLLINFO

该结构允许您完整的指定滚动条参数。cbSize必须设置成SCROLLINFO结构的大小。fMask是标志位,指出结构中其它域包含什么样的有效数据。nMin和nMax包含滚动条的最小和最大滚动值。如果fMask参数包含SIF_RANGE标志,Windows就会在这两个域中查找这些值。同样地,如果fMask包含SIF_POS标志,nPos在预定义的范围内设置滚动条位置。

nPage域允许程序定义屏幕当前可视区域相对于整个滚动区域的大小。这可以给用户一个大致印象,整个滚动区域中当前有多少是可视的。只有当fMask中包含SIF_PAGE标志的时候这个域才有用。SCROLLINFO结构的最后一个成员是nTrackPos,但SetScrollInfo不使用并忽略掉它了。

fMask最后一个标志是SIF_DISABLENOSCROLL,可以让滚动条失效但可视。当整个滚动范围在可视区域内可视且不再需要滚动的时候,用这个方法是很方便的。在这种情况下,使滚动条失效比简单的移去整个滚动条更好一些。

细心的读者一定会注意到SCROLLINFO结构中域的宽度问题。nMin,nMax和nPos是整型,在Windows CE中是32位宽。而另一方面,WM_HSCROLL和WM_VSCROLL消息只能在WParam参数的高字位中返回一个16位的位置数据。如果您使用的滚动范围超过65,535,那么可以使用GetScrollInfo函数,其原型如下:BOOL GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);

和SetScrollInfo一样,fnBar中的标志位用来指出传递给函数的窗口句柄种类。SCROLLINFO结构同SetScrollInfo中的一样。在传给GetScrollInfo之前,必须先用结构的大小来始化cbSize。应用程序必须通过设置fMask中的适当标志,来指明希望函数返回什么数据。fMask中使用的标志同SetScrollInfo中使用的一样,同时增加了两个。现在可以传递SIF_TRACKPOS标志来让滚动条返回当前滑块位置。在WM_xSCROLL消息期间调用时,nTrackPos包含实时位置,而nPos包含的是开始拖动滑块时的滚动条位置。

滚动条是与众不同的控件,因为只要简单指定窗口风格,就可以很容易地把滚动条添加到窗口中;另外它是放置在窗口客户区域外边地。原因是应用程序普遍需要滚动条,所以Windows的开发者就尽量使绑定滚动条到窗口的工作更容易。现在,来看一看其它基本Windows控件。

CtlView示例程序
清单4-1给出了CtlView示例程序,它演示了我刚才描述的所有控件。
该示例程序使用了几个应用程序定义的子窗口,其中包含了各种控件。您可以通过点主窗口顶部的5个单选框,在不同子窗口之间进行切换。

当每个控件通过WM_COMMAND消息来发送通知时,通知消息会显示在窗口右边的列表框里。CtlView可以很方便的观察到控件给父窗口发送什么了消息和什么时候发送的消息。CtlView可根据屏幕宽度使用不同控件布局。这意味着即使在具有狭窄屏幕的Pocket PC上,依然可以看到所有控件。

清单4-1:CtlView 程序
CtlView.h
//======================================================================
// Header file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
// Returns number of elements
#define dim(x) (sizeof(x) / sizeof(x[0]))
//----------------------------------------------------------------------
// Generic defines and data types
//
struct decodeUINT { // Structure associates
UINT Code; // messages
// with a function.
LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM);
};
struct decodeCMD { // Structure associates
UINT Code; // menu IDs with a
LRESULT (*Fxn)(HWND, WORD, HWND, WORD); // function.
};

//----------------------------------------------------------------------
// Generic defines used by application
#define IDI_BTNICON 20 // Icon used on button

#define ID_ICON 1 // Icon ID
#define IDC_CMDBAR 2 // Command bar ID
#define IDC_RPTLIST 3 // Report window ID

// Client window IDs go from 5 through 9.
#define IDC_WNDSEL 5 // Starting client
// window IDs

// Radio button IDs go from 10 through 14.
#define IDC_RADIOBTNS 10 // Starting ID of
// radio buttons

// Button window defines
#define IDC_PUSHBTN 100
#define IDC_CHKBOX 101
#define IDC_ACHKBOX 102
#define IDC_A3STBOX 103
#define IDC_RADIO1 104
#define IDC_RADIO2 105
#define IDC_OWNRDRAW 106
// Edit window defines
#define IDC_SINGLELINE 100
#define IDC_MULTILINE 101
#define IDC_PASSBOX 102

// List box window defines
#define IDC_COMBOBOX 100
#define IDC_SNGLELIST 101
#define IDC_MULTILIST 102

// Static control window defines
#define IDC_LEFTTEXT 100
#define IDC_RIGHTTEXT 101
#define IDC_CENTERTEXT 102
#define IDC_ICONCTL 103
#define IDC_BITMAPCTL 104
// Scroll bar window defines
#define IDC_LRSCROLL 100
#define IDC_UDSCROLL 101

// User-defined message to add a line to the window
#define MYMSG_ADDLINE (WM_USER + 10)

typedef struct {
TCHAR *szClass;
int nID;
TCHAR *szTitle;
int x;
int y;
int cx;
int cy;
DWORD lStyle;
} CTLWNDSTRUCT, *PCTLWNDSTRUCT;

typedef struct {
WORD wMsg;
int nID;
WPARAM wParam;
LPARAM lParam;
} CTLMSG, * PCTLMSG;

typedef struct {
TCHAR *pszLabel;
WORD wNotification;
} NOTELABELS, *PNOTELABELS;
//----------------------------------------------------------------------
// Function prototypes
//
HWND InitInstance (HINSTANCE, LPWSTR, int);
int TermInstance (HINSTANCE, int);

// Window procedures
LRESULT CALLBACK FrameWndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ClientWndProc (HWND, UINT, WPARAM, LPARAM);

// Message handlers
LRESULT DoCreateFrame (HWND, UINT, WPARAM, LPARAM);
LRESULT DoSizeFrame (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandFrame (HWND, UINT, WPARAM, LPARAM);
LRESULT DoAddLineFrame (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDestroyFrame (HWND, UINT, WPARAM, LPARAM);

//----------------------------------------------------------------------
// Window prototypes and defines for BtnWnd
//
#define BTNWND TEXT ("ButtonWnd")
int InitBtnWnd (HINSTANCE);

// Window procedures
LRESULT CALLBACK BtnWndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT DoCreateBtnWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCtlColorBtnWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandBtnWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDrawItemBtnWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoMeasureItemBtnWnd (HWND, UINT, WPARAM, LPARAM);

//----------------------------------------------------------------------
// Window prototypes and defines for EditWnd
//
#define EDITWND TEXT ("EditWnd")
int InitEditWnd (HINSTANCE);
// Window procedures
LRESULT CALLBACK EditWndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT DoCreateEditWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandEditWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDrawItemEditWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoMeasureItemEditWnd (HWND, UINT, WPARAM, LPARAM);
//----------------------------------------------------------------------
// Window prototypes and defines for ListWnd
//
#define LISTWND TEXT ("ListWnd")
int InitListWnd (HINSTANCE);

// Window procedures
LRESULT CALLBACK ListWndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT DoCreateListWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandListWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDrawItemListWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoMeasureItemListWnd (HWND, UINT, WPARAM, LPARAM);

//----------------------------------------------------------------------
// Window prototypes and defines for StatWnd
//
#define STATWND TEXT ("StaticWnd")
int InitStatWnd (HINSTANCE);

// Window procedures
LRESULT CALLBACK StatWndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT DoCreateStatWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandStatWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDrawItemStatWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoMeasureItemStatWnd (HWND, UINT, WPARAM, LPARAM);

//----------------------------------------------------------------------
// Window prototypes and defines ScrollWnd
//
#define SCROLLWND TEXT ("ScrollWnd")
int InitScrollWnd (HINSTANCE);

// Window procedures
LRESULT CALLBACK ScrollWndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT DoCreateScrollWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoVScrollScrollWnd (HWND, UINT, WPARAM, LPARAM);
LRESULT DoHScrollScrollWnd (HWND, UINT, WPARAM, LPARAM);

CtlView.cpp
//======================================================================
// CtlView - Lists the available fonts in the system.
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include <commctrl.h> // Command bar includes
#include "CtlView.h" // Program-specific stuff
//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT ("CtlView");
HINSTANCE hInst; // Program instance handle

// Message dispatch table for FrameWindowProc
const struct decodeUINT FrameMessages[] = {
WM_CREATE, DoCreateFrame,
WM_SIZE, DoSizeFrame,
WM_COMMAND, DoCommandFrame,
MYMSG_ADDLINE, DoAddLineFrame,
WM_DESTROY, DoDestroyFrame,
};

typedef struct {
TCHAR *szTitle;
int nID;
TCHAR *szCtlWnds;
HWND hWndClient;
} RBTNDATA;

// Text for main window radio buttons
TCHAR *szBtnTitle[] = {TEXT ("Buttons"), TEXT ("Edit"), TEXT ("List"),
TEXT ("Static"), TEXT ("Scroll")};
// Class names for child windows containing controls
TCHAR *szCtlWnds[] = {BTNWND, EDITWND, LISTWND, STATWND, SCROLLWND};

int nWndSel = 0;

//======================================================================
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
MSG msg;
int rc = 0;
HWND hwndFrame;

// Initialize application.
hwndFrame = InitInstance (hInstance, lpCmdLine, nCmdShow);
if (hwndFrame == 0)
return 0x10;

// Application message loop
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
// Instance cleanup
return TermInstance (hInstance, msg.wParam);
}
//----------------------------------------------------------------------
// InitInstance - Instance initialization
//
HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow) {
WNDCLASS wc;
HWND hWnd;

// Save program instance handle in global variable.
hInst = hInstance;

#if defined(WIN32_PLATFORM_PSPC)
// If Pocket PC, allow only one instance of the application
hWnd = FindWindow (szAppName, NULL);
if (hWnd) {
SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
return 0;
}
#endif
// Register application frame window class.
wc.style = 0; // Window style
wc.lpfnWndProc = FrameWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetSysColorBrush (COLOR_STATIC);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = szAppName; // Window class name

if (RegisterClass (&wc) == 0) return 0;

// Initialize client window classes
if (InitBtnWnd (hInstance) != 0) return 0;
if (InitEditWnd (hInstance) != 0) return 0;
if (InitListWnd (hInstance) != 0) return 0;
if (InitStatWnd (hInstance) != 0) return 0;
if (InitScrollWnd (hInstance) != 0) return 0;

// Create frame window.
hWnd = CreateWindowEx (WS_EX_NODRAG, szAppName, TEXT ("Control View"),
WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
// Return fail code if window not created.
if (!IsWindow (hWnd)) return 0;

// Standard show and update calls
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);

return hWnd;
}
//----------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {

return nDefRC;
}
//======================================================================
// Message handling procedures for FrameWindow
//
//----------------------------------------------------------------------
// FrameWndProc - Callback function for application window
//
LRESULT CALLBACK FrameWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(FrameMessages); i++) {
if (wMsg == FrameMessages[i].Code)
return (*FrameMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateFrame - Process WM_CREATE message for window.
//
LRESULT DoCreateFrame (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
HWND hwndChild;
INT i;

// Set currently viewed window
nWndSel = 0;
// Create the radio buttons.
for (i = 0; i < dim(szBtnTitle); i++) {
hwndChild = CreateWindow (TEXT ("BUTTON"),
szBtnTitle[i], BS_AUTORADIOBUTTON |
WS_VISIBLE | WS_CHILD, 0,
0, 80, 20, hWnd,
(HMENU)(IDC_RADIOBTNS+i), hInst, NULL);

// Destroy frame if window not created.
if (!IsWindow (hwndChild)) {
DestroyWindow (hWnd);
break;
}
}
// Create report window. Size it so that it fits either on the right
// or below the control windows, depending on the size of the screen.
hwndChild = CreateWindowEx (WS_EX_CLIENTEDGE, TEXT ("listbox"),
TEXT (""), WS_VISIBLE | WS_CHILD | WS_VSCROLL |
LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT, 0, 0,
100, 100,hWnd, (HMENU)IDC_RPTLIST, hInst, NULL);

// Destroy frame if window not created.
if (!IsWindow (hwndChild)) {
DestroyWindow (hWnd);
return 0;
}
// Initialize tab stops for display list box.
i = 24;
SendMessage (hwndChild, LB_SETTABSTOPS, 1, (LPARAM)&i);

// Create the child windows. Size them so that they fit under
// the command bar and fill the left side of the child area.
for (i = 0; i < dim(szCtlWnds); i++) {
hwndChild = CreateWindowEx (WS_EX_CLIENTEDGE, szCtlWnds[i],
TEXT (""), WS_CHILD, 0, 0, 200, 200, hWnd,
(HMENU)(IDC_WNDSEL+i), hInst, NULL);

// Destroy frame if client window not created.
if (!IsWindow (hwndChild)) {
DestroyWindow (hWnd);
return 0;
}
}
// Check one of the auto radio buttons.
SendDlgItemMessage (hWnd, IDC_RADIOBTNS+nWndSel, BM_SETCHECK, 1, 0);
hwndChild = GetDlgItem (hWnd, IDC_WNDSEL+nWndSel);
ShowWindow (hwndChild, SW_SHOW);
return 0;
}
//----------------------------------------------------------------------
// DoSizeFrame - Process WM_SIZE message for window.
//
LRESULT DoSizeFrame (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int nWidth, nHeight;
int i, x, y, cx, cy;
BOOL bWide = TRUE;
RECT rect;
GetWindowRect (hWnd, &rect);
GetClientRect (hWnd, &rect);
// These arrays are used to adjust between wide and narrow screens.
POINT ptRBtnsN[] = {{5,0}, {90,0}, {180,0}, {5,20}, {90,20}};
POINT ptRBtnsW[] = {{5,0}, {90,0}, {180,0}, {270,0}, {360,0}};
LPPOINT pptRbtns = ptRBtnsW;

nWidth = LOWORD (lParam);
nHeight = HIWORD (lParam);

// Use different layouts for narrow (Pocket PC) screens.
if (GetSystemMetrics (SM_CXSCREEN) < 480) {
pptRbtns = ptRBtnsN;
bWide = FALSE;
}
// Move the radio buttons.
for (i = 0; i < dim(szBtnTitle); i++)
SetWindowPos (GetDlgItem (hWnd, IDC_RADIOBTNS+i), 0,
pptRbtns[i].x, pptRbtns[i].y,
0, 0, SWP_NOSIZE | SWP_NOZORDER);

// Size report window so that it fits either on the right or
// below the control windows, depending on the size of the screen.
x = bWide ? nWidth/2 : 0;
y = bWide ? 20 : (nHeight)/2 + 40;
cx = bWide ? nWidth/2 : nWidth;
cy = nHeight - y;

SetWindowPos (GetDlgItem (hWnd, IDC_RPTLIST), 0, x, y, cx, cy,
SWP_NOZORDER);

// Size the child windows so that they fit under
// the command bar and fill the left side of the child area.
x = 0;
y = bWide ? 20 : 40;
cx = bWide ? nWidth/2 : nWidth;
cy = bWide ? nHeight : (nHeight)/2+40;

for (i = 0; i < dim(szCtlWnds); i++)
SetWindowPos (GetDlgItem (hWnd, IDC_WNDSEL+i), 0, x, y, cx, cy,
SWP_NOZORDER);
return 0;
}
//----------------------------------------------------------------------
// DoCommandFrame - Process WM_COMMAND message for window.
//
LRESULT DoCommandFrame (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
HWND hwndTemp;
int nBtn;
// Don't look at list box messages.
if (LOWORD (wParam) == IDC_RPTLIST)
return 0;
nBtn = LOWORD (wParam) - IDC_RADIOBTNS;
if (nWndSel != nBtn) {

// Hide the currently visible window.
hwndTemp = GetDlgItem (hWnd, IDC_WNDSEL+nWndSel);
ShowWindow (hwndTemp, SW_HIDE);

// Save the current selection.
nWndSel = nBtn;
// Show the window selected via the radio button.
hwndTemp = GetDlgItem (hWnd, IDC_WNDSEL+nWndSel);
ShowWindow (hwndTemp, SW_SHOW);
}
return 0;
}
//----------------------------------------------------------------------
// DoAddLineFrame - Process MYMSG_ADDLINE message for window.
//
LRESULT DoAddLineFrame (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TCHAR szOut[128];
int i;

if (LOWORD (wParam) == 0xffff)
wsprintf (szOut, TEXT (" \t %s"), (LPTSTR)lParam);
else
wsprintf (szOut, TEXT ("id:%3d \t %s"), LOWORD (wParam),
(LPTSTR)lParam);

i = SendDlgItemMessage (hWnd, IDC_RPTLIST, LB_ADDSTRING, 0,
(LPARAM)(LPCTSTR)szOut);

if (i != LB_ERR)
SendDlgItemMessage (hWnd, IDC_RPTLIST, LB_SETTOPINDEX, i,
(LPARAM)(LPCTSTR)szOut);
return 0;
}
//----------------------------------------------------------------------
// DoDestroyFrame - Process WM_DESTROY message for window.
//
LRESULT DoDestroyFrame (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PostQuitMessage (0);
return 0;
}

BtnWnd.cpp
//======================================================================
// BtnWnd - Button window code
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "Ctlview.h" // Program-specific stuff

extern HINSTANCE hInst;

LRESULT DrawButton (HWND hWnd, LPDRAWITEMSTRUCT pdi);
//----------------------------------------------------------------------
// Global data
//

// Message dispatch table for BtnWndWindowProc
const struct decodeUINT BtnWndMessages[] = {
WM_CREATE, DoCreateBtnWnd,
WM_CTLCOLORSTATIC, DoCtlColorBtnWnd,
WM_COMMAND, DoCommandBtnWnd,
WM_DRAWITEM, DoDrawItemBtnWnd,
};

// Structure defining the controls in the window
CTLWNDSTRUCT Btns [] = {
{TEXT ("BUTTON"), IDC_PUSHBTN, TEXT ("Button"),
10, 10, 120, 23, BS_PUSHBUTTON | BS_NOTIFY},
{TEXT ("BUTTON"), IDC_CHKBOX, TEXT ("Check box"),
10, 35, 120, 23, BS_CHECKBOX},
{TEXT ("BUTTON"), IDC_ACHKBOX, TEXT ("Auto check box"),
10, 60, 110, 23, BS_AUTOCHECKBOX},
{TEXT ("BUTTON"), IDC_A3STBOX, TEXT ("Multiline auto 3-state box"),
140, 60, 90, 52, BS_AUTO3STATE | BS_MULTILINE},
{TEXT ("BUTTON"), IDC_RADIO1, TEXT ("Auto radio button 1"),
10, 85, 120, 23, BS_AUTORADIOBUTTON},
{TEXT ("BUTTON"), IDC_RADIO2, TEXT ("Auto radio button 2"),
10, 110, 120, 23, BS_AUTORADIOBUTTON},
{TEXT ("BUTTON"), IDC_OWNRDRAW, TEXT ("OwnerDraw"),
150, 10, 44, 44, BS_PUSHBUTTON | BS_OWNERDRAW},
};
// Structure labeling the button control WM_COMMAND notifications
NOTELABELS nlBtn[] = {{TEXT ("BN_CLICKED "), 0},
{TEXT ("BN_PAINT "), 1},
{TEXT ("BN_HILITE "), 2},
{TEXT ("BN_UNHILITE"), 3},
{TEXT ("BN_DISABLE "), 4},
{TEXT ("BN_DOUBLECLICKED"), 5},
{TEXT ("BN_SETFOCUS "), 6},
{TEXT ("BN_KILLFOCUS"), 7}
};
// Handle for icon used in owner-draw icon
HICON hIcon = 0;
//----------------------------------------------------------------------
// InitBtnWnd - BtnWnd window initialization
//
int InitBtnWnd (HINSTANCE hInstance) {
WNDCLASS wc;

// Register application BtnWnd window class.
wc.style = 0; // Window style
wc.lpfnWndProc = BtnWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = BTNWND; // Window class name

if (RegisterClass (&wc) == 0) return 1;

return 0;
}

//======================================================================
// Message handling procedures for BtnWindow
//----------------------------------------------------------------------
// BtnWndWndProc - Callback function for application window
//
LRESULT CALLBACK BtnWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(BtnWndMessages); i++) {
if (wMsg == BtnWndMessages[i].Code)
return (*BtnWndMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateBtnWnd - Process WM_CREATE message for window.
//
LRESULT DoCreateBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;

for (i = 0; i < dim(Btns); i++) {

CreateWindow (Btns[i].szClass, Btns[i].szTitle,
Btns[i].lStyle | WS_VISIBLE | WS_CHILD,
Btns[i].x, Btns[i].y, Btns[i].cx, Btns[i].cy,
hWnd, (HMENU) Btns[i].nID, hInst, NULL);
}
hIcon = LoadIcon (hInst, TEXT ("TEXTICON"));

// We need to set the initial state of the radio buttons.
CheckRadioButton (hWnd, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1);
return 0;
}
//----------------------------------------------------------------------
// DoCtlColorBtnWnd - process WM_CTLCOLORxx messages for window.
//
LRESULT DoCtlColorBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
return (LRESULT)GetStockObject (WHITE_BRUSH);
}
//----------------------------------------------------------------------
// DoCommandBtnWnd - Process WM_COMMAND message for window.
//
LRESULT DoCommandBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TCHAR szOut[128];
int i;
// Since the Check Box button is not an auto check box, it
// must be set manually.
if ((LOWORD (wParam) == IDC_CHKBOX) &&
(HIWORD (wParam) == BN_CLICKED)) {
// Get the current state, complement, and set.
i = SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_GETCHECK, 0, 0);
if (i == 0)
SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_SETCHECK, 1, 0);
else
SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_SETCHECK, 0, 0);
}

// Report WM_COMMAND messages to main window.
for (i = 0; i < dim(nlBtn); i++) {
if (HIWORD (wParam) == nlBtn[i].wNotification) {
lstrcpy (szOut, nlBtn[i].pszLabel);
break;
}
}
if (i == dim(nlBtn))
wsprintf (szOut, TEXT ("notification: %x"), HIWORD (wParam));

SendMessage (GetParent (hWnd), MYMSG_ADDLINE, wParam,
(LPARAM)szOut);
return 0;
}
//----------------------------------------------------------------------
// DoDrawItemBtnWnd - Process WM_DRAWITEM message for window.
//
LRESULT DoDrawItemBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {

return DrawButton (hWnd, (LPDRAWITEMSTRUCT)lParam);
}

//---------------------------------------------------------------------
// DrawButton - Draws an owner-draw button
//
LRESULT DrawButton (HWND hWnd, LPDRAWITEMSTRUCT pdi) {
HPEN hPenShadow, hPenLight, hPenDkShadow, hRedPen, hOldPen;

HBRUSH hBr, hOldBr;
LOGPEN lpen;
TCHAR szOut[128];
POINT ptOut[3], ptIn[3];
// Reflect the messages to the report window.
wsprintf (szOut, TEXT ("WM_DRAWITEM Act:%x State:%x"),
pdi->itemAction, pdi->itemState);
SendMessage (GetParent (hWnd), MYMSG_ADDLINE, pdi->CtlID,
(LPARAM)szOut);

// Create pens for drawing.
lpen.lopnStyle = PS_SOLID;
lpen.lopnWidth.x = 3;
lpen.lopnWidth.y = 3;
lpen.lopnColor = GetSysColor (COLOR_3DSHADOW);
hPenShadow = CreatePenIndirect (&lpen);

lpen.lopnColor = RGB (255, 0, 0);
hRedPen = CreatePenIndirect (&lpen);

lpen.lopnWidth.x = 1;
lpen.lopnWidth.y = 1;
lpen.lopnColor = GetSysColor (COLOR_3DLIGHT);
hPenLight = CreatePenIndirect (&lpen);

lpen.lopnColor = GetSysColor (COLOR_3DDKSHADOW);
hPenDkShadow = CreatePenIndirect (&lpen);

// Create a brush for the face of the button.
hBr = CreateSolidBrush (GetSysColor (COLOR_3DFACE));

// Draw a rectangle with a thick outside border to start the
// frame drawing.
hOldPen = (HPEN_SelectObject (pdi->hDC, hPenShadow);
hOldBr = (HBRUSH)SelectObject (pdi->hDC, hBr);
Rectangle (pdi->hDC, pdi->rcItem.left, pdi->rcItem.top,
pdi->rcItem.right, pdi->rcItem.bottom);

// Draw the upper left inside line.
ptIn[0].x = pdi->rcItem.left + 1;
ptIn[0].y = pdi->rcItem.bottom - 2;
ptIn[1].x = pdi->rcItem.left + 1;
ptIn[1].y = pdi->rcItem.top + 1;
ptIn[2].x = pdi->rcItem.right - 2;
ptIn[2].y = pdi->rcItem.top + 1;
// Select a pen to draw shadow or light side of button.
if (pdi->itemState & ODS_SELECTED) {
SelectObject (pdi->hDC, hPenDkShadow);
} else {
SelectObject (pdi->hDC, hPenLight);
}
Polyline (pdi->hDC, ptIn, 3);
// If selected, also draw a bright line inside the lower
// right corner.
if (pdi->itemState & ODS_SELECTED) {
SelectObject (pdi->hDC, hPenLight);
ptIn[1].x = pdi->rcItem.right - 2;
ptIn[1].y = pdi->rcItem.bottom - 2;
Polyline (pdi->hDC, ptIn, 3);
}

// Now draw the black outside line on either the upper left or lower
// right corner.
ptOut[0].x = pdi->rcItem.left;
ptOut[0].y = pdi->rcItem.bottom - 1;
ptOut[2].x = pdi->rcItem.right - 1;
ptOut[2].y = pdi->rcItem.top;

SelectObject (pdi->hDC, hPenDkShadow);
if (pdi->itemState & ODS_SELECTED) {
ptOut[1].x = pdi->rcItem.left;
ptOut[1].y = pdi->rcItem.top;
} else {
ptOut[1].x = pdi->rcItem.right - 1;
ptOut[1].y = pdi->rcItem.bottom - 1;
}
Polyline (pdi->hDC, ptOut, 3);

// Draw the triangle.
ptOut[0].x = (pdi->rcItem.right - pdi->rcItem.left)/2;
ptOut[0].y = pdi->rcItem.top + 4;
ptOut[1].x = pdi->rcItem.left + 3;
ptOut[1].y = pdi->rcItem.bottom - 6;
ptOut[2].x = pdi->rcItem.right - 6;
ptOut[2].y = pdi->rcItem.bottom - 6;
SelectObject (pdi->hDC, hRedPen);
Polygon (pdi->hDC, ptOut, 3);

// If button has the focus, draw the dotted rect inside the button.
if (pdi->itemState & ODS_FOCUS) {
pdi->rcItem.left += 3;
pdi->rcItem.top += 3;
pdi->rcItem.right -= 4;
pdi->rcItem.bottom -= 4;
DrawFocusRect (pdi->hDC, &pdi->rcItem);
}
// Clean up. First select the original brush and pen into the DC.
SelectObject (pdi->hDC, hOldBr);
SelectObject (pdi->hDC, hOldPen);

// Now delete the brushes and pens created.
DeleteObject (hBr);
DeleteObject (hPenShadow);
DeleteObject (hPenDkShadow);
DeleteObject (hPenLight);
return 0;
}

EditWnd.cpp
//======================================================================
// EditWnd - Edit control window code
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "Ctlview.h" // Program-specific stuff

extern HINSTANCE hInst;
//----------------------------------------------------------------------
// Global data
//
// Message dispatch table for EditWndWindowProc
const struct decodeUINT EditWndMessages[] = {
WM_CREATE, DoCreateEditWnd,
WM_COMMAND, DoCommandEditWnd,
};

// Structure defining the controls in the window
CTLWNDSTRUCT Edits[] = {
{TEXT ("edit"), IDC_SINGLELINE, TEXT ("Single line edit control"),
10, 10, 180, 23, ES_AUTOHSCROLL},

{TEXT ("edit"), IDC_MULTILINE, TEXT ("Multiline edit control"),
10, 35, 180, 70, ES_MULTILINE | ES_AUTOVSCROLL},
{TEXT ("edit"), IDC_PASSBOX, TEXT (""),
10, 107, 180, 23, ES_PASSWORD},
};
// Structure labeling the edit control WM_COMMAND notifications
NOTELABELS nlEdit[] = {{TEXT ("EN_SETFOCUS "), 0x0100},
{TEXT ("EN_KILLFOCUS"), 0x0200},
{TEXT ("EN_CHANGE "), 0x0300},
{TEXT ("EN_UPDATE "), 0x0400},
{TEXT ("EN_ERRSPACE "), 0x0500},
{TEXT ("EN_MAXTEXT "), 0x0501},
{TEXT ("EN_HSCROLL "), 0x0601},
{TEXT ("EN_VSCROLL "), 0x0602},
};
//----------------------------------------------------------------------
// InitEditWnd - EditWnd window initialization
//
int InitEditWnd (HINSTANCE hInstance) {
WNDCLASS wc;

// Register application EditWnd window class.
wc.style = 0; // Window style
wc.lpfnWndProc = EditWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = EDITWND; // Window class name

if (RegisterClass (&wc) == 0) return 1;

return 0;
}
//======================================================================
// Message handling procedures for EditWindow
//----------------------------------------------------------------------
// EditWndWndProc - Callback function for application window
//
LRESULT CALLBACK EditWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(EditWndMessages); i++) {
if (wMsg == EditWndMessages[i].Code)
return (*EditWndMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateEditWnd - Process WM_CREATE message for window.
//
LRESULT DoCreateEditWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;

for (i = 0; i < dim(Edits); i++) {

CreateWindow (Edits[i].szClass, Edits[i].szTitle,
Edits[i].lStyle | WS_VISIBLE | WS_CHILD | WS_BORDER,
Edits[i].x, Edits[i].y, Edits[i].cx, Edits[i].cy,
hWnd, (HMENU) Edits[i].nID, hInst, NULL);
}
return 0;
}
//----------------------------------------------------------------------
// DoCommandEditWnd - Process WM_COMMAND message for window.
//
LRESULT DoCommandEditWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TCHAR szOut[128];
int i;

for (i = 0; i < dim(nlEdit); i++) {
if (HIWORD (wParam) == nlEdit[i].wNotification) {
lstrcpy (szOut, nlEdit[i].pszLabel);
break;
}
}

if (i == dim(nlEdit))
wsprintf (szOut, TEXT ("notification: %x"), HIWORD (wParam));

SendMessage (GetParent (hWnd), MYMSG_ADDLINE, wParam,
(LPARAM)szOut);
return 0;
}

ListWnd.cpp
//======================================================================
// ListWnd - List box control window code
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "Ctlview.h" // Program-specific stuff

extern HINSTANCE hInst;
//----------------------------------------------------------------------
// Global data
//
// Message dispatch table for ListWndWindowProc
const struct decodeUINT ListWndMessages[] = {
WM_CREATE, DoCreateListWnd,
WM_COMMAND, DoCommandListWnd,
};

// Structure defining the controls in the window
CTLWNDSTRUCT Lists[] = {
{TEXT ("combobox"), IDC_COMBOBOX, TEXT (""), 10, 10, 205, 100,
WS_VSCROLL},

{TEXT ("Listbox"), IDC_SNGLELIST, TEXT (""), 10, 35, 100, 90,
WS_VSCROLL | LBS_NOTIFY},

{TEXT ("Listbox"), IDC_MULTILIST, TEXT (""), 115, 35, 100, 90,
WS_VSCROLL | LBS_EXTENDEDSEL | LBS_NOTIFY}
};
// Structure labeling the list box control WM_COMMAND notifications
NOTELABELS nlList[] = {{TEXT ("LBN_ERRSPACE "), (-2)},
{TEXT ("LBN_SELCHANGE"), 1},
{TEXT ("LBN_DBLCLK "), 2},
{TEXT ("LBN_SELCANCEL"), 3},
{TEXT ("LBN_SETFOCUS "), 4},
{TEXT ("LBN_KILLFOCUS"), 5},
};
// Structure labeling the combo box control WM_COMMAND notifications
NOTELABELS nlCombo[] = {{TEXT ("CBN_ERRSPACE "), (-1)},
{TEXT ("CBN_SELCHANGE "), 1},
{TEXT ("CBN_DBLCLK "), 2},
{TEXT ("CBN_SETFOCUS "), 3},
{TEXT ("CBN_KILLFOCUS "), 4},
{TEXT ("CBN_EDITCHANGE "), 5},
{TEXT ("CBN_EDITUPDATE "), 6},
{TEXT ("CBN_DROPDOWN "), 7},
{TEXT ("CBN_CLOSEUP "), 8},
{TEXT ("CBN_SELENDOK "), 9},
{TEXT ("CBN_SELENDCANCEL"), 10},
};
//----------------------------------------------------------------------
// InitListWnd - ListWnd window initialization
//
int InitListWnd (HINSTANCE hInstance) {
WNDCLASS wc;

// Register application ListWnd window class.
wc.style = 0; // Window style
wc.lpfnWndProc = ListWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW); // Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = LISTWND; // Window class name

if (RegisterClass (&wc) == 0) return 1;

return 0;
}
//======================================================================
// Message handling procedures for ListWindow
//----------------------------------------------------------------------
// ListWndProc - Callback function for application window
//
LRESULT CALLBACK ListWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(ListWndMessages); i++) {
if (wMsg == ListWndMessages[i].Code)
return (*ListWndMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateListWnd - Process WM_CREATE message for window.
//
LRESULT DoCreateListWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
TCHAR szOut[64];
for (i = 0; i < dim(Lists); i++) {

CreateWindow (Lists[i].szClass, Lists[i].szTitle,
Lists[i].lStyle | WS_VISIBLE | WS_CHILD | WS_BORDER,
Lists[i].x, Lists[i].y, Lists[i].cx, Lists[i].cy,
hWnd, (HMENU) Lists[i].nID, hInst, NULL);
}
for (i = 0; i < 20; i++) {
wsprintf (szOut, TEXT ("Item %d"), i);
SendDlgItemMessage (hWnd, IDC_SNGLELIST, LB_ADDSTRING, 0,
(LPARAM)szOut);

SendDlgItemMessage (hWnd, IDC_MULTILIST, LB_ADDSTRING, 0,
(LPARAM)szOut);

SendDlgItemMessage (hWnd, IDC_COMBOBOX, CB_ADDSTRING, 0,
(LPARAM)szOut);
}
// Set initial selection.
SendDlgItemMessage (hWnd, IDC_COMBOBOX, CB_SETCURSEL, 0, 0);
return 0;
}
//----------------------------------------------------------------------
// DoCommandListWnd - Process WM_COMMAND message for window.
//
LRESULT DoCommandListWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TCHAR szOut[128];
int i;

if (LOWORD (wParam) == IDC_COMBOBOX) {
for (i = 0; i < dim(nlCombo); i++) {
if (HIWORD (wParam) == nlCombo[i].wNotification) {
lstrcpy (szOut, nlCombo[i].pszLabel);
break;
}
}
if (i == dim(nlList))
wsprintf (szOut, TEXT ("notification: %x"), HIWORD (wParam));
} else {
for (i = 0; i < dim(nlList); i++) {
if (HIWORD (wParam) == nlList[i].wNotification) {
lstrcpy (szOut, nlList[i].pszLabel);
break;
}
}
if (i == dim(nlList))
wsprintf (szOut, TEXT ("notification: %x"), HIWORD (wParam));
}
SendMessage (GetParent (hWnd), MYMSG_ADDLINE, wParam,
(LPARAM)szOut);
return 0;
}
StatWnd.cpp
//======================================================================
// StatWnd - Static control window code
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "Ctlview.h" // Program-specific stuff

extern HINSTANCE hInst;
//----------------------------------------------------------------------
// Global data
//
// Message dispatch table for StatWndWindowProc
const struct decodeUINT StatWndMessages[] = {
WM_CREATE, DoCreateStatWnd,
WM_COMMAND, DoCommandStatWnd,
};

// Structure defining the controls in the window
CTLWNDSTRUCT Stats [] = {
{TEXT ("static"), IDC_LEFTTEXT, TEXT ("Left text"),
10, 10, 120, 23, SS_LEFT | SS_NOTIFY},

{TEXT ("static"), IDC_RIGHTTEXT, TEXT ("Right text"),
10, 35, 120, 23, SS_RIGHT},

{TEXT ("static"), IDC_CENTERTEXT, TEXT ("Center text"),
10, 60, 120, 23, SS_CENTER | WS_BORDER},
};
// Structure labeling the static control WM_COMMAND notifications
NOTELABELS nlStatic[] = {{TEXT ("STN_CLICKED"), 0},
{TEXT ("STN_ENABLE "), 2},
{TEXT ("STN_DISABLE"), 3},
};
//----------------------------------------------------------------------
// InitStatWnd - StatWnd window initialization
//
int InitStatWnd (HINSTANCE hInstance) {
WNDCLASS wc;

// Register application StatWnd window class.
wc.style = 0; // Window style
wc.lpfnWndProc = StatWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = STATWND; // Window class name

if (RegisterClass (&wc) == 0) return 1;

return 0;
}
//======================================================================
// Message handling procedures for StatWindow
//----------------------------------------------------------------------
// StatWndProc - Callback function for application window
//
LRESULT CALLBACK StatWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. I

分享到:
评论

相关推荐

    lazarus-1.0.8-fpc-2.6.2-cross-arm-wince-win32

    lazarus-1.0.8-fpc-2.6.2-cross-arm-wince-win32 freepascal 用于开发WINCE程序

    .net-cf-wince-curve.rar_WINCE 曲线_WINCE 曲线_wince 曲线控件_曲线 wince_

    描述中的".net-cf-wince-curve.rar"是一个包含用于Windows CE平台的曲线绘制控件的压缩文件。该控件可能提供API和方法,使开发者能够轻松地在Wince设备上生成实时数据曲线,这对于需要实时监测和分析数据的科学仪器...

    Lazarus-0.9.28.2-fpc-2.2.4-cross-arm-wince-win32

    标题 "Lazarus-0.9.28.2-fpc-2.2.4-cross-arm-wince-win32" 暗示了一个用于开发针对Windows CE(掌上设备操作系统)应用程序的开源集成开发环境(IDE)——Lazarus的一个特定版本。Lazarus是Free Pascal编译器(FPC...

    WINCE程序设计 WINCE程序设计

    《WINCE程序设计》深入解析 Windows CE(简称WinCE)是微软公司开发的一款嵌入式操作系统,主要用于掌上设备、工业控制、汽车电子、医疗设备等领域的应用。它的设计思路是将完整的Windows桌面系统精简,形成一个轻...

    hobd汉化版-wince

    标题 "hobd汉化版-wince" 指向的是一个专为Windows CE(Wince)操作系统汉化的HOBD软件版本。HOBD,全称是"Handy OBD-II",是一款用于汽车诊断的工具,它可以连接到车辆的OBD-II接口,读取并解析车载计算机的数据,...

    C# 各种文件格式的转换 ----winCE试验版

    C# 各种文件格式的转换 ----winCE试验版 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA 源码 毕业设计 开题报告 答辩PPT等

    仪表控件-wince下能运行

    标题中的“仪表控件-wince下能运行”指的是在Windows Embedded Compact(简称Wince)操作系统上可以正常运行的一种专门设计用于模拟或显示各种工业、汽车或其他设备中常见仪表的软件控件。Windows CE是微软开发的一...

    qt-wince安装.pdf

    首先,你需要下载适用于Windows CE的Qt源代码包,例如`qt-embedded-wince-opensource-src-4.4.0.zip`。 2. **安装Visual Studio 2005** 安装Visual Studio 2005是必要的,因为Qt的构建系统依赖于其编译器。在安装...

    wince程序设计 wince程序设计 wince程序设计

    在本文中,我们将深入探讨Windows CE(WinCE)程序设计的关键知识点,包括其架构、开发环境、编程语言支持以及实际应用案例。 1. Windows CE 架构: Windows CE是一个模块化、可裁剪的操作系统,可以适应各种硬件...

    qt-wince安装.docx

    - Qt的嵌入式开发包:qt-embedded-wince-opensource-src-4.4.0.zip - Microsoft Visual Studio 2005 (VS2005),用于编译和调试 - Windows Mobile 5.0 Pocket PC SDK,提供针对Windows CE的开发环境 - Microsoft ...

    wince程序设计教程

    2. 界面设计:Windows CE支持标准的Windows GUI组件,如窗口、控件、菜单等,可以创建丰富的用户界面。 3. 多线程编程:Wince支持多线程,允许并发执行任务,提高程序性能。 4. 文件系统:Wince采用FAT或NTFS文件...

    VS2005-CoreCon-x86-WINCE600,wince开发软件安装包

    "VS2005-CoreCon-x86-WINCE600"这个安装包就是专门为Windows CE 6.00平台的开发设计的,它包含了构建、调试和测试嵌入式应用程序所需的工具和组件。 首先,"CoreCon"是Visual Studio 2005中的核心连接组件,它是...

    博创2410开发板光盘资料----WINCE实验指导书

    - **实验目的**: 掌握使用MFC框架开发WinCE应用程序的方法。 - **实验内容**: - 设计简单的用户界面。 - 实现基本的应用逻辑。 - 测试应用程序的功能。 #### 4.3 基于WINCEDIRECTSHOW的多媒体播放机实验 - **...

    3G-USB-WINCE驱动,支持华为部分无线网卡

    兼容wince5.0/6.0 以下列出的是调试通过的型号列表,仅供参考. 1. WCDMA/DSDPA: Hua Wei E180 Hua Wei E220 Hua Wei E1750(Modem:COM6,ATCMD:COM8,COM7 not use) Hua Wei E1550 Hua Wei E156G(Modem:COM6,ATCMD:...

    IDA教程-WinCE ARM调试器入门教程.pdf

    IDA教程-WinCE ARM调试器入门教程.pdf

    最新Qt-WinCE全解

    注意,WinCE可能不支持某些桌面版Qt的功能,所以需要查阅文档以确认兼容性。 3. **配置项目**: 配置项目文件(.pro),确保它指定了正确的Qt模块和WinCE特定的编译选项。 4. **编译和调试**: 在开发环境中编译项目,...

    wince程序设计中文版1

    wince程序设计中文影印版 积分要多了,不好意思,我也不知道怎么取消 一共三个压缩包,须全部下载了解压,只让传10m,没办法啊 part1 http://download.csdn.net/source/257557 part2 ...

    Image-update--WinCE-6.0.rar_gk7000_update WINCE_wince 6.0

    标题中的“Image-update--WinCE-6.0.rar_gk7000_update WINCE_wince 6.0”指的是一个针对Windows CE 6.0操作系统进行更新的镜像文件,该更新是针对名为“gk7000”的特定硬件平台设计的。在Windows CE系统中,"image...

    基于ARM-WinCE的电机监控系统设计.pdf

    基于ARM-WinCE的电机监控系统设计是指使用ARM处理器作为核心,Windows CE操作系统作为软件平台,实现对电机的监控和控制。该系统可以对电机的步进电机和直流电机的表面温度、转速和运行时间等参数进行实时监控。 ...

    Wince程序设计 第三版

    《Wince程序设计 第三版》是一本深入探讨Windows CE.NET平台编程的权威指南,主要针对希望在嵌入式系统中开发应用程序的程序员。这本书详细介绍了如何利用Microsoft的嵌入式操作系统来创建高效、功能丰富的应用程序...

Global site tag (gtag.js) - Google Analytics