MiniGUI细节处理(转)

MiniGUI编程--列表框

分类: minigui2009-11-04 20:40
列表框
LBS(ListBoxStyle)
以CTRL_LIST/"list"为类名调用CreateWindow
多选风格:LBS_MULTIPLESEL
高级风各:LBS_USEICON
LBS_CHECKBOX
LBS_AUTOCHECK
加上边框WS_BORDER
加垂直滚动条WS_VSCROLL
加水平滚动条WS_HSCROLL
允许通知消息:LBS_NOTIFY
排序LBS_SORT
常用风格组合:
LBS_NOTIFY|LBS_SORT|WS_VSCROLL|WS_BORDER
加入字符串LB_ADDSTRING
最上面索引值为0
SendMessage传递字符串时节lParam指向字符串
添加以未尾
SendMessage(hwndlist,LB_ADDSTRING,0,(LPARAM)string);
插入字符串LB_INSERTSTRING
SendMessage(hwndlist,LB_INSERTSTRING,index,(LPARAM)string);
如指定期LBS_CHECKBOX/LBS_USEICON风格添加时不能传字符串指针,而要使用LISTBOXITEMINFO结构
HICON hIcon1;
LISTBOXITEMINFO lbii;
hIcon1=LoadIconFromFile(HDC_SCREEN,"res/audio.ico",1);
lbii.hIcon=hIcon1;
lbii.cmFlag=CMFLAG_CHECKED;
lbii.string="ABCDEFG";
SendMessage(hwnd,LB_ADDSTRING,0,(LPARAM)&lbii);
cmFlag:CMFLAG_CHECKED,CMFLAG_BLANK,CMFLAG_PARTCHECKED
在列表框中显示位图
IMGFLAG_BITMAP
lbii.hIcon=(DWORD)GetSystemBitmap(SYSBMP_MAXIMIZE);
lbii.cmFlag=CMFLAG_CHECKED|IMGFLAG_BITMAP;
lbii.string="ABCDEF";
SendMessage(hwndlist,LB_ADDSTRING,0,(LPARAM)&lbii);
删除指定条目
发送LB_DELETESTRING消息
SendMessage(hwndlist,LB_DELETESTRING,index,0);
清空
SendMessage(hwndlist,LB_DELETESTRING,0,0);
获取条目个数
发送LB_GETCOUNT消息
count=SendMessage(hwndlist,LB_GETCOUNT,0,0);
获取指定条目字符串长度
发送LB_GETTEXTLEN
length=SendMessage(hwndlist,LB_GETTEXTLEN,index,0);
获取条目
length=SendMessage(hwndlist,LB_GETTEXTLEN,index,(LPARAM)buffer);
设置条目
LB_SETTEXT
SendMessage(hwndlist,LB_SETTEXT,index,buffer);
高级列形框要使用LB_GETITEMDATA/LB_SETITEMDATA
HICON hIocn1;
LISTBOXITEMINFO lbii;
hIcon1=LoadIconFromFile(HDC_SCREEN,"rest/audio.ico",1);
lbii.hIcon=hIcon1;
lbii.cmFlag=CMFLAG_CHECKED;
lbii.string="new item";
SendMessage(hwndlist,LB_SETITEMDATA,index,(LPARAM)&lbii);
获取当前选择项
LB_GETCURSEL
index=SendMessage(hwndlist,LB_GETCURSEL,0,0);
设置当前选择项
SendMessage(hwndlist,LB_SETCURSEL,index,0);
多选:
LB_GETSELCOUNT获得被选中的条目个数
LB_GETSELITEMS获得所有被选索引值
int i,sel_count;
int *sel_itmes;
sel_count=SendMessage(hwndlist,LB_GETSELCOUNT,0,0L);
if(sel_count==0)
return;
sel_items=alloca(sizeof(int)*sel_count);
SendMessage(hwndlist,LB_GETSELITEMS,sel_count,sel_items);
for(i=0;i...
查所字符串
模糊查找LB_FINDSTRING
精确查找LB_FINDSTRINGEXACT
index=SendMessage(hwndlist,LB_FINDSTRING,(LPARAM)string);
获取检查框状态
status=SendMessage(hwndlist,LB_GETCHECKMARK,index,0);
返回值:
CMFLAG_CHECKED选择状态
CMFLAG_PARTCHECKED部分选择状态
CMFLAG_BLANK未选择状态
设检查框状态
ret=SendMessage(hwndlist,LB_SETCHECKMARK,index,(LPARAM)status);
返回值:
LB_ERR失败
LB_OKAY成功
为每个条目附加一个32位数据,在需要时取出该值
LB_SETITEMADDDATA
LB_GETITEMADDDATA
设置条目所占高度
LB_SETITEMHEIGHT
返回条目所占高度
LB_GETITEMHEIGHT
通知码:
必须指定LBS_NOTIFY风格
LBN_ERRSPACE内存分配失败
LBN_SELCHANGE当前选择项发生变化
LBN_CLICKED单击
LBN_DBLCLK双击
LBN_SELCANCEL取消选择
LBN_SETFOCUS列表框获得焦点
LBN_KILLFOCUS列表框失去焦点
LBN_CLICKCHECKMARK单击条目检查框
LBN_ENTER在列表框中按下Enter键
只有指下LBS_NOTIFY时,列表框才会向父窗口发送通知消息
如果用SetNotificationCallback设定了通知回调函数
则控件不发送MSG_COMMAND通知消息,而会直接调用设定的通知回调函数

MiniGUI编程--编辑框

2009-11-04 20:41
编辑框
ES(EditStyle)
单行CTRL_SLEDIT/"sledit"  SingleLineEdit
多行CTRL_MLEDIT/"textedit"  MultiLineEdit
通用风格
WS_CHILD|WS_VISIBLE|WS_BORDER
特有风格:
ES_UPPERCASE大写
ES_LOWERCASE小写
ES_PASSWORD密码
ES_READONLY只读
ES_BASELINE显示虚线
ES_AUTOWRAP自动换行
ES_LEFT左对齐
ES_NOHIDESEL失去焦点保持文本的选中状态
ES_AUTOSELECT得到焦点时自动先选中所有
ES_TITLE第一行显示标题
ES_TIP提示信息
ES_CENTER文本居中对齐
ES_RIGHT文本右对齐
多行文本框指定滚动条:
WS_HSCROLL
WS_VSCROLL
消息:
MSG_GETTEXTLENGTH获取文本长度
MSG_GETTEXT获取文本
MSG_SETTEXT设置文本
或用以下函数
GetWindowTextLength
GetWindowText
SetWindowText
取得插入符位置
EM_GETCARETPOS
int line_pos;
int char_pos;
SendMessage(hwndedit,EM_GETCARETPOS,(WPARAM)&line_pos,(LPARAM)&char_pos);
参数:
line_pos行索引值
char_pos该行中的字符位置
设置插入符位置
EM_SETCARETPOS
int line_pos;
int char_pos;
SendMessage(hwndedit,EM_SETCARETPOS,line_pos,char_pos);
获取当前选中文本
EM_GETSEL
char buffer[buf_len];
SendMessage(hwndedit,EM_GETSEL,buf_len,(LPARAM)buffer);
设置当前选中的文本
EM_SETSEL
int line_pos,char_pos;
SendMessage(hwndedit,EM_SETSEL,line_pos,char_pos);
lParam指定行索引值,wParam指定行内字符位置
获取当前选择点位置
EM_GETSELPOS
int line_pos,char_pos;
SendMessage(hwndedit,EM_GETSELPOS,(WPARAM)&line_pos,(LPARAM)&char_pos);
选择所有字符相当于Ctrl+A
EM_SELECTALL
SendMessage(hwndedit,EM_SELECTALL,0,0);
复制到剪贴板Ctrl+C
EM_COPYTOCB CopyToClipBoard
SendMessage(hwndedit,EM_COPYTOCB,0,0);
粘贴到编辑框Ctrl+V
EM_INSERTCBTEXT InsertClipBoardText
SendMessage(hwndedit,EM_INSERTCBTEXT,0,0);
剪切Ctrl+X
EM_CUTTOCB CutToClipBoard
SendMessage(hwndedit,EM_CUTTOCB,0,0);
获取行高
EM_GETLINEHEIGHT
int line_height;
line_height=SendMessage(hwndedit,EM_GETLINEHEIGHT,0,0);
设置行高
EM_SETLINEHEIGHT
int line_height;
SendMessage(hwndedit,EM_SETLINEHEIGHT,line_height,0);
获取行数
EM_GETLINECOUNT
int line_count;
line_count=SendMessage(hwndedit,EM_GETLINECOUNT,0,0);
设置文本上限
EM_LIMITTEXT
SendMessage(hwndedit,EM_LIMITTEXT,10,0L);
设置只读
EM_SETREADONLY wParam为TRUE
取消只读
EM_SETREADONLY wParam为FALSE
修改密码显示字符
EM_SETPASSWORDCHAR
SendMessage(hwndedit,EM_SETPASSWORDCHAR,'%',0L);
获得当前密码字符
EM_GETPASSWORDCHAR
设置提示文字
SLEDIT控件具有ES_TIP风格时
ES_SETTIPTEXT
获取提示文字
ES_GETTIPTEXT
int len;
char *tip_text;
SendMessage(hwndedit,ES_SETTIPTEXT,len,(LPARAM)tip_text);
lParam指定字符串,wParam指定长度

int len;
char tip_text[len+1];
SendMessage(hwndedit,EM_GETTIPTEXT,len,(LPARAM)tip_text);
lParam指定缓冲区,wParam指定长度
当TEXTEDIT具有ES_TITLE风格时
EM_SETTITLETEXT设置标题文字
EM_GETTITLETEXT获取标题文字
int len;
char *title_text;
SendMessage(hwndedit,EM_SETTITLETEXT,len,(LPARAM)title_text);
lParam指定字符串,wParam指定长度

int len;
char title_text[len+1];
SendMessage(hwnd,EM_GETTITLETEXT,len,(LPARAM)title_text)
lParam指定缓冲区,wParam指定长度
编辑框通知码
编辑框没有ES_NOTIFY风格
EN_SETFOCUS
EN_KILLFOCUS
EN_CHANGE
EN_ENTER
EN_MAXTEXT
EN_CLICKED
EN_DBLCLK

控件专用函数
GetNotificationCallback获取控件的通知消息的回调函数
SetNotificationCallback设置控件的通知消息的回调函数
NotifyParentEx发送控件通知消息

MiniGUI编程--静态框

分类: minigui2009-11-04 20:43
静态框
以CTRL_STATIC/"static"为类名调用CreateWindow即可创建
风格
普通
SS_SIMPLE
SS_LEFT
SS_CENTER
SS_RIGHT
SS_LEFTNOWORDWRAP
位图
SS_BITMAP
SS_ICON
dwAddData指定位图/图标对象指针
SS_CENTERIMAGE
SS_REALSIZEIMAGE
CreateWindow(CTRL_STATIC,"",WS_CHILD|SS_BITMAP|WS_VISIBLE,IDC_STATIC,280,80,50,50,hwnd,(DWORD)GetSystemBitmap(SYSBMP_CHECKMARK));

CreateWindow(CTRL_STATIC,"",WS_CHILD|SS_ICON|WS_VISIBLE,IDC_STATIC,280,80,50,50,hwnd,(DWORD)GetLargeSystemIcon(IDI_INFOMATION));

CreateWindow(CTRL_STATIC,"",WS_CHILD|SS_BITMAP|SS_CENTERIMAGE|SS_REALSIZEIMAGE|WS_VISIBLE,IDC_STATIC,280,80,50,50,hwnd,(DWORD)GetSystemBitmap(SYSBMP_CHECKMARK));
指定分组框(框架)
SS_GROUPBOX
颜色风格
SS_WHITERECT
SS_GRAYRECT
SS_BLACKRECT
SS_WHITEFRAME
SS_BLACKFRAME
SS_GRAYFRAME
通知码
必须设置SS_NOTIFY风格
单击STN_CLICKED
双击STN_DBLCLK
按钮
以CTRL_BUTTON/"button"为类我调用CreateWindow可创建按钮
默认按钮:BS_DEFPUSHBUTTON
按钮向父窗口发送MSG_COMMAND和BN_CLICKED
多行风格:BS_MULTILINE
位图风格:BS_BITMAP
图标风格:BS_ICON
通过CreateWindow的dwAddData传递位图/图标对象的句柄
保持原有大小:BS_REALSIZEIMAGE
复选框
在按钮基础上指定以下两种风格:
BS_CHECKBOX手动向控件发消息设置
BS_AUTOCHECKBOX自动设置小圆点
BS_3STATE
BS_AUTO3STATE
文字位置:
BS_LEFTTEXT
BS_LEFT
BS_CENTER
BS_RIGHT
BS_TOP
BS_VCENTER
BS_BOTTOM
单选按钮
风格:
BS_RADIOBUTTON
BS_AUTORADIOBUTTON
文本位置:
BS_LEFTTEXT
BS_LEFT
BS_CENTER
BS_RIGHT
BS_TOP
BS_VCENTER
BS_BOTTOM
互斥在第一个单选钮按设置WS_GROUP
按钮消息
查询/设置选中消息BM_GETCHECK/BM_SETCHECK
BM_GETSTATE/BM_SETSTATE
BM_GETIMAGE/BM_SETIMAGE
BM_CLICK
模拟
SendMessage(hwndbtn,BM_SETCHECK,BST_CHECKED,0);
按钮通知码:
BS_NOTIFY
/
BN_CLICKED
BN_PUSHED
BN_UNPUSHED
BN_DBLCLK
BN_SETFOCUS
BN_KILLFOCUS
CheckDlgButton
CheckRadioButton
IsDlgButtonChecked

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/creatory/archive/2007/12/03/1914461.aspx

MiniGUI编程--组合框

分类: minigui2009-11-04 20:39
组合框
以CTRL_COMBOBOX/"combobox"为类名调用CreateWindow
风格CBS->ComboBoxStyle
简单组合框CBS_SIMPLE
下拉式组合框CBS_DROPDOWNLIST
在用CreateWindow创建组合框时用dwAddData参数指定列表框高度值
hcomb=CreateWindow(CTRL_COMBOBOX,"0",WS_VISIBLE|WS_TABSTOP|CBS_SIMPLE|CBS_SORT,IDC_BOX4,10,100,180,24,parent,100);
//指定dwAddData为100,即简单组合框列表框的高度为100
旋转组合框CBS_SPINLIST
箭头在内容的左右风格:CBS_SPINARROW_LEFTRIGHT
箭头在内容的上下风格:CBS_SPINARROW_TOPBOTTOM
其他风格:
CBS_READONLY
CBS_UPPERCASE
CBS_LOWERCASE
CBS_EDITBASELINE
CBS_SORT
CBS_EDITNOBORDER无边框
CBS_AUTOFOCUS组合框获得焦点,自动定位于编辑框中
旋钮数字框
以CBS_AUTOSPIN风格创建
自动循环显示风格CBS_AUTOLOOP
组合框消息
CB_ADDSTRING
CB_INSERTSTRING
CB_DELETESTIRNG
CB_FINDSTRING
CB_FINDSTRINGEXACT
CB_GETCOUNT
CB_GETCURSEL
CB_SETCURSEL
CB_RESETCONTENT
CB_GETITEMADDDATA
CB_SETITEMADDDATA
CB_GETITEMHEIGHT
CB_SETITEMHEIGHT
CB_SETSTRINGCMPFUNC
CB_GETLBTEXT
CB_GETLBTEXTLEN
CB_GETCHILDREN
CB_LIMITTEXT
CB_SETEDITSEL
CB_GETEDITSEL
旋钮组合框消息
CB_SPIN 向前向后wParam控制方向0为下1为上
CB_FASTSPIN  快速向前向后wParam控制方向0为下1为上
旋钮数字框消息
CB_GETSPINRNAGE 获得可取的最大值和最小值
CB_SETSPINRANGE 设置可取的最大值和最小值
CB_SETSPINVALUE 设置编辑框当前值
CB_GETSPINVALUE 获得编辑框当前值
组合框通知码
CBN->ComboBoxNotify
CBN_ERRSPACE
CBN_SELCHANGE
CBN_EDITCHANGE
CBN_DBLCLK
CBN_CLICKED
CBN_SETFOCUS
CBN_KILLFOCUS
CBN_DROPDOWN
CBN_CLOSEUP
CBN_SELENDOK
CBN_SELENDCANCEL
菜单按钮
以CTRL_MENUBUTTON为类名调用CreateWindow
一般风格:WS_CHILD|WS_VISIBLE|MBS_SORT
MBS->MenuButtonStyle
MBS_SORT
MBS_LEFTARROW
MBS_NOBUTTON
MBS_ALIGNLEFT
MBS_ALIGNRIGHT
MBS_ALIGNCENTER
向菜单按钮添加条目
使用MBM_ADDITEM消息和MENUBUTTONITEM结构
MENUBUTTONITEM mbi;
mbi.text="item one";
mbi.bmp=NULL;
mbi.data=0;
pos=SendMessage(hmbtnwnd,MBM_ADDITEM,-1,(LPARAM)&mbi);
从菜单按钮删除条目
MBM_DELITEM
SendMessage(hMbtnwnd,MBM_DELITEM,index,0);
删除所有条目
MBM_RESETCTRL
SendMessage(hMbtnwnd,MBM_RESETCTRL,0,0);
设置当前选中条目
MBM_SETCURITEM
SendMessage(hMbtnwnd,MBM_SETCURITEM,index,0);
获得当前选中条目
MBM_GETCURITEM
index=SendMessage(hMbtnwnd,MBM_GETCURITEM,0,0);
获取条目数据
MBM_GETITEMDATA wParam指定索引值,lParam指向一个MENUBUTTONITEM结构的指针对性
设置条目数据
MBM_SETITEMDATA
which指定要获取的数据项
MB_WHICH_TEXT
MB_WHICH_BMP
MB_WHICH_ATTDATA
MENUBUTTONITEM mbi;
mbi.which=MB_WHICH_TEXT|MB_WHICH_ATTDATA;
mbi.text="newtext";
mbi.data=1;
SendMessage(menubtn,MBM_SETITEMDATA,0,(LPARAM)&mbi);
通知消息:
MBN->MenuButtonNotify
MBN_ERRSPACE
MBN_SELECTED
MBN_CHANGED
MBN_STARTMENU
MBN_ENDMENU

进度条
以CTRL_PROGRESSBAR为类名调用CreateWindow创建
风格:PBS->ProgressBarStyle
PBS_NOTIFY使进度条产生通知消息
PBS_VERTICAL竖直显示进度条
通用风格:
WS_CHILD|WS_VISIBLE|PBS_NOTIFY
进度条设置
PBM->ProgressBarModify
设置范围
PBM_SETRANGE
SendMessage(hwndpb,PBM_SETRANGE,min,max);
设置步长
PBM_SETSTEP
SendMessage(hwndpb,PBM_SETSTEP,5,0);
设置当前进度
PBM_SETPOS
SendMessage(hwndpb,PBM_SETPOS,50,0);
在当前进度基础上偏移
PBM_DELTAPOS
SendMessage(hwndpb,PBM_DELTAPOS,10,0);
前进一个步进值
PBM_STEPIT
SendMessage(hwndpb,PBM_STEPIT,0,0);
进度条通知码
指定PBS_NOTIFY风格
PBN_REACHMAX
PBN_REACHMIN
滑块
以CTRL_TRACKBAR为类名调用CreateWindow
通用风格WS_CHILD|WS_VISIBLE|TBS_NOTIFY
竖直滑块TBS_VERTICAL
TBS_TIP
TBS_NOTICK
TBS_BORDER
滑块消息
TBM_SETRANGE
TBM_GETMIN
TBM_GETMAX
TBM_SETMIN
TBM_SETMAX
TBM_SETLINESIZE
TBM_GETLINESIZE
TBM_SETPAGESIZE
TBM_GETPAGESIZE
TBM_SETPOS
TBM_GETPOS
TBM_SETTICKFREQ
TBM_SETTIP
TBM_GETTIP
滑块通知码
指定TBS_NOTIFY风格
TBN_CHANGE
TBN_REACHMAX
TBN_REACHMIN
工具栏
CTRL_TOOLBAR
CTRL_NEWTOOLBAR
CTRL_COOLBAR
以CTRL_NEWTOOLBAR为类名调用CreateWindow创建
创建工具栏
填充NTBINFO结构赋给CreateWindow的dwAddData能数
NTBINFO->NewToolBarINFO
成员
image
nr_cells
nr_cols
w_cell
h_cell
风格
NTBS_HORIZONTAL
NTBS_VERTICAL
NTBS_MULTLINE
NTBS_WITHTEXT
NTBS_TEXTRIGHT
NTBS_DRAWSTATES
NTBS_DRAWSEPARATOR
添加工具项
发送NTBM_ADDITEM消息传递NTBITEMINFO结构
成员
which :NTBM_GETTITEM/NTBM_SETITEM
flags :NTBIF_PUSHBUTTON/NTBIF_CHECKBUTTON/NTBIF_HOTSPOTBUTTON/NTBIF_NEWLINE
id    :按钮标识符
text  :指定NTBS_WITHTEXT风格时显示的文本
tip   :保留
bmp_cell
hotspot_proc
rc_hotspot
add_data

MiniGUI消息投递方式

分类: minigui2009-11-04 20:38
消息发送方式:
1.将消息投递到一个先进先出队列中
2.直接把消息发给窗口过程

投递到队列中的消息主要有:
键盘和鼠标消息MSG_LBUTTONDOWN,MSG_MOUSEMOVE,MSG_KEYDOWN,MSG_CHAR
定时器消息MSG_TIMER
绘制消息MSG_PAINT
退出消息MSG_QUIT
可以用HavePendingMessage函数检查消息队列中是否有消息而不取出的消息
BOOL GUIAPI HavePendingMessage(HWND hMainWnd);

直接发送到窗口过程的消息一般用于通知窗口完成一些需要立即处理的事件,如MSG_ERASEBKGND消息

消息的处理
一般通过一个消息循环来处理消息队列中的消息
GetMessage从消息队列中取出消息
TranslateMessage翻译消息
DispatchMessage发送消息
如下:
MSG msg;
HWND hMainWnd;
MAINWINCREATE CreateInfo;
InitCreateInfo(&CreateInfo);
hMainWnd=CreateMainWindow(&CreateInfo);
if(hMainWnd==HWND_INVALID)
return -1;
while(GetMessage(&msg,hMainWnd))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
在Thread中当要求等待消息立即返回以处理其他事务时可以使用HavePendingMessage
do
{
ReadMasterPty(pConInfo);
if(pConInfo->terminate)
break;
while(HavePendingMessage(hMainWnd))
{
if(!GetMessage(&msg,hMainWnd))
break;
DispatchMessage(&msg);
}
}while(true);
窗口过程是一个特定类型的函数,用于接收和处理所有发送到该窗口的消息
每个控件类也有一个窗口过程,属于同一控件类的所有控件共用同一个窗口过程处理消息
如果窗口过程不处理某些消息一般把该消息传给系统进行默认处理
int DefaultMainWinProc(HWND hwnd,int message,WPARAM wParam,LPARAM lParam);
对话框缺省消息处理函数
int DefaultDialogProc(HWND hwnd,int message,WPARAM wParam,LPARAM lParam);
控件窗口缺省消息处理函数
int DefaultControlProc(HWND hwnd,int message,WPARAM wParam,LPARAM lParam);
投递:把一条消息复制到消息队列中
发送: 直接把消息发送到窗口过程函数
消息处理函数:
PostMessage:将消息放到消息队列后立即返回,用于发送非关键性消息,受消息缓冲区限制
SendMessage:将消息发送到窗口过程,等待处理完后返回
SendNotifyMessage:同PostMessage,采用链表处理,不受缓冲区限制,一般用于从控件向父窗口发送“通知消息”
PostQuitMessage:将MSG_QUIT消息投递到消息队列中
将指定消息广播给桌面的所有主窗口:
int GUIAPI BroadcastMessage(int iMsg,WPARAM wParam,LPARAM lParam);
丢弃消息队列中所有消息并返回个数
int GUIAPI ThrowAwayMessages(HWND pMainWnd);
等待一有消息就返回
BOOL GUIAPI WaitMessage(PMSG pMsg,HWND hMainWnd);
MiniGUI消息大全:
1.MSG_DESTROY
调用DestroyMainWindow/DestroyWindow时发送到窗口过程中
例:程序在MSG_DESTROY消息中销毁被托管主窗口的位图字体等资料
case MSG_DESTROY:
     DestroyIocn(icon1);
     DestroyIocn(icon2);
     DestroyAllControls(hWnd);
     return 0;
例:被托管主窗口响应MSG_CLOSE消息
case MSG_CLOSE:
     DestroyMainWindow(hWnd);
     MainWindowCleanup(hWnd);
     return 0;

2.MSG_CLOSE
点击“X”按钮时向窗口过程发送该消息,程序该在响应该消息时调用DestroyMainWindow销毁主窗口并用PostQuitMessage向队列中投放MSG_QUIT消息
3.MSG_PAINT
窗口进行重绘时该消息被发送到窗口过程
窗口在初始显示时
从隐藏状态变为显示状态
从部分不可见到可见状态
调用InvalidateRect时
窗口过程在收到该消息时应该对窗口进行界面维护
case MSG_PAINT:
 HDC hdc;
 hdc=BeginPaint(hwnd);
 ...
 EndPaint(hwnd,hdc);
 return 0;
程序处理完后要直接返回,不应该再传递给默认窗口过程处理
4.MSG_ERASEBKGND
需要清除窗口背景时发送该消息
InvalidateRect/UpdateWindow并为bErase传递TRUE时
如果在MSG_PAINT消息时重绘所有的窗口客户区应忽略该消息
case MSG_ERASEBKGND:
 return 0;
在窗口背景上填充图片:
case MSG_ERASEBKGND:
HDC hdc=(HDC)wParam;
const RECt *clip=(const RECT*)lParam;
BOOL fGetDC=FALSE;
RECT rcTemp;
if(hdc==0)
{
hdc=GetClientDC(hwnd);
fGetDC=TRUE;
}
if(clip)
{
rcTemp=*clip;
ScreenToClient(hDlg,&rcTemp.left,&rcTemp.top);
ScreenToClient(hDlg,&rcTemp.right,&rcTemp.bottom);
IncludeClipRect(hdc,&rcTemp);
}
FillBoxWithBitmap(hdc,0,0,0,0,&bmp_bkgnd);
if(fGetDC)
ReleaseDC(hdc);
return 0;
5.MSG_FONTCHANGED
调用SetWindowFont改变了默认字体后将引发该消息
窗口过程需要处理以便反映出新的字体设置
如编辑框就要处理并重绘自己:
case MSG_FONTCHANGED:
{
sled=(PSLEDITDATA)GetWindowAdditionalData2(hwnd);
sled->startpos=0;
sled->editpos=0;
edtGetLineInfo(hwnd,sled);
DestroyCaret(hwnd);
CreateCaret(hwnd,NULL,1,GetWindowFont(hwnd)->size);
SetCaretPos(hwnd,sled->leftMargin,sled->topMargin);
InvalidateRect(hwnd,NULL,TRUE);
return 0;
}
6.MSG_FONTCHANGING
当调用SetWindowFont改变默认字体时引发该消息
通常窗口过程将此消息传递给默认窗口过程处理
如果窗口不允许用户改变字体可以加以截获该消息将返回非零值
case MSG_FONTCHANGING:
     return -1;
7.MSG_CREATE
窗口成功创建并添加到窗口管理器中时引发该消息
8.MSG_SIZECHANGED
窗口尺寸变化时发生,wParam包含窗口大小,lParam用于保存窗口客户区大小的RECT指针
case MSG_SIZECHANGED:
RECT *rcClient=(RECT*)lParam;
rcClient->right=rcClient->left+_WIDTH;
rcClient->bottom=rcClient->top+_HEIGHT;
return 0;
9.MSG_SIZECHANGING
窗口尺寸发生变化时引发该消息,用于确定窗口大小
wParam包含预期窗口尺寸值,lParam用于保存结果值
case MSG_SIZECHANGING:
 memcpy((PRECT)lParam,(PRECT)wParam,sizeof(RECT));
 return 0;
可以截获该消息使创建的窗口位于指定的位置或具有固定的大小
case MSG_SIZECHANGING:
const RECT *rcExpect=(const RECT*)wParam;
RECT*rcResult=(RECT*)lParam;
rcResult->left=rcExcept->left;
rcResult->top=rcExcept->top;
return 0;
10.MSG_NCCREATE
建立主窗口过程中引发, 此时窗口对象尚未建立,不能使用GetDC等函数
必须在此消息的处理中进行输入法窗口注册
case MSG_NCCREATE:
if(hz_input_init())
SendMessage(HWND_DESKTOP,MSG_IME_REGISTER,(WPARAM)hwnd,0);
else
return -1;
break;
MiniGUI通用窗口操作函数,可用于主窗口和控件
UpdateWindow  立即更新某个窗口
ShowWindow    显示/隐藏某个窗口
IsWindowVisible 判断某个窗口是否可见
EnableWindow 激活/禁止某个窗口
IsWindowEnabled 判断某个窗口是否可用
GetClientRect 取得客户区矩形
GetWindowRect 取得窗口矩形
GetWindowBkColor 取得窗口背景色
SetWindowBkColor 设置窗口背景色
GetWindowFont 取得窗口默认字体
SetWindowFont 设置窗口默认字体
GetWindowCursor 取得窗口光标
SetWindowCursor 设置窗口光标
GetWindowStyle 取得窗口风格
GetWindowExStyle 取得窗口扩展风格
GetFocusChild 取得有输入焦点的子窗口
SetFocusChild 设置焦点子窗口
GetWindowCallbackProc 取得窗口过程函数
SetWindowCallbackProc 设置窗口过程函数
GetWindowAdditionalData 取得窗口附加数据一
SetWindooAdditionalData 设置窗口附加数据一
GetWindowAdditionalData2
SetWindowAdditionalData2
GetWindowCaption 获取窗口标题
SetWindowCaption 设置窗口标题
InvalidateRect 使窗口给定矩形区域无效,将引发窗口重绘
GetUpdateRect 获取窗口当前无效区域外包矩形
ClientToScreen 客户区坐标转换为屏幕坐标
ScreenToClient 屏幕坐标转换为客户区坐标
WindowToScreen窗口坐标转换为屏幕坐标
ScreenToWindow
IsMainWindow判断给定窗口是否为主窗口
IsControl判断给定窗口控件
IsDialog断送给定窗口是否为对话框
GetParent获取父窗口句柄,主窗口父窗口为HWND_DESKTOP
GetMainWindowHandle获取某个窗口的主窗口句柄
GetNextChild取得下一个子窗口
GetNextMainWindow取得下一个主窗口句柄
GetHosting获取某个窗口的托管窗口
GetFirstHosted 取得某个主窗口的第一个被托管窗口
GetNextHosted 获取下一人被托管窗口
GetActiveWindow 取得当前活动窗口
SetActiveWindow 设置当前活动窗口
GetCapture获取当前捕获鼠标的窗口
SetCapture捕获
ReleaseCapture释放
MoveWindow移动/改变窗口大小
ScrollWindow滚动窗口客户区内容
创建简单的控件
调用CreateWindow直接创建子窗口
或使用对话框模板创建一类控件
模板结构中定义
用于定义控件
typedef struct
{
char *class_name; //控件类
DWORD dwStyle; //风格
int x,y,w,h; //控件在对话框中的位置
int id; //控件ID
const char *caption; //控件标题
DWORD dwAddData; //附加数据
DWORD dwExStyle; //扩展风格
}CTRLDATA;
typedef CTRLDATA *PCTRLDATA;
用于定义对话框模板
typedef struct
{
DWORD dwStyle; //对话框风格
DWORD dwExStyle; //对话框扩展风格
int x,y,w,h; //对话框位置
const char*caption; //对话框标题
HICON hIcon; //对话框图标
HMENU hMenu; //对话框菜单
int controllnr; //控件数目
PCTRLDATA controls; //指同控件数组的指针
DWORD dwAddData;  //附加数据,必须为0
}DLGTEMPLATE;
typedef DLGTEMPLATE *PDLGTEMPLATE;
结构CTRLDATA用于定义控件,DLGTEMPLATE用于定义对话框本身
程序应首先用CTRLDATA定义对话框中所有的控件并用数组表示
控件在数组中的顺序就是用户按TAB时的切换顺序
然后定义对话框
指定对话框中的控件数目
并指定DLGTEMPLATE->controls指向控件数组
例:
static DLGTEMPLATE DlgInitProcess=
{
WS_BORDER|WS_CAPTION,
WS_EX_NONE,
120,150,400,130,
"VAM-CNC正在初始化",
0,0,
3,NULL,
0
};
static CTRLDATA CtrlInitProcess=
{
{"static",
WS_VISIBLE|SS_SIMPLE,
10,10,380,16,
IDC_PROMPTINFO,
"正在...",
0
},
{
"processbar",
WS_VISIBLE,
10,40,380,20,
IDC_PROCESS,
NULL,
0
},
{
"button",
WS_TABSTOP|WS_VISIBLE|BS_DEFPUSHBUTTON,
170,70,60,25,
ID_OK,
"确定",
0
}
};
应尽量将定义的对话框模板数据接口定义为static类型,使其仅在该文件中有效,以免造成错误

MiniGUI对话框编程

分类: minigui2009-11-04 20:38
定义对话框模板后,再定义对话框回调函数并调用DialogBoxIndirectParam建立对话框
例:
static int InitDialogBoxProc(HWND hDlg,int message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case MSG_INITDIALOG:
return 1;
case MSG_COMMAND:
switch(wParam)
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg,wParam);
break;
}
break;
}
return DefaultDialogProc(hDlg,message,wParam,lParam);
}

static void InitDialogBox(HWND hWnd)
{
DlgInitProcess.controls=CtrlInitProcess;
DialogBoxIndirectParam(&DlgInitProcess,hWnd,InitDialogBoxProc,0L);
}
创建对话框函数
int GUIAPI DialogBoxIndirectParam(PDLGTEMPLATE pDlgTemplate,HWND hOwner,WNDPROC DlgProc,LPARAM lParam);
参数:对话框模板,托管主窗口句柄,回调函数地址,附加参数值
BOOL GUIAPI EndDialog(HWND hDlg,int endcode);
结束对话框过程
void GUIAPI DestroyAllControls(HWND hDlg);
销毁对话框中所有子控件
创建非模态对话框
HWND GUIAPI CreateMainWindowIndirect(PDLGTEMPLATE pDlgTemplate,HWND hOwner,WNDPROC WndProc);
BOOL GUIAPI DestroyMainWindowIndirect(HWND hMainWin);
例:
static int InitWindowProc(HWND hDlg,int message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case MSG_COMMAND:
swtich(wParam)
{
case IDOK:
case IDCANCEL:
DestroyMainWindowIndirect(hWnd);
break;
}
break;
}
return DefaultWindowProc(hDlg,message,wParam,lParam);
}
...
{
HWND hwnd;
MSG msg;
DlgInitProcess.controls=CtrlInitProcess;
hwnd=CreateMainWindowIndirect(&DlgInitProcess,HWND_DESKTOP,InitWindowProc);
if(hwnd==HWND_INVALID)
return -1;
while(GetMessage(&msg,hwnd))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
对话框控件风格
WS_GROUP  成为同组控件头一个
WS_TABSTOP 支持TAB切换
对话框操作函数:
DestroyAllControls
GetDlgCtrlID
GetDlgItem
GetDlgItemInt
SetDlgItemInt
GetDlgItemText
GetDlgItemText2
SetDlgItemText
GetNextDlgGroupItem
GetNextDlgGroupItem
SendDlgItemMessage
CheckDlgButton
CheckRadioButton
IsDlgButtonChecked
GetDlgDefPushButton
MinGUI预定义控件类:
"static" CTRL_STATIC
"button" CTRL_BUTTON
"sledit" CTRL_SLEDIT (Single Line)
"mledit" CTRL_MLEDIT (Multi Line)
"textbox" CTRL_TEXTBOX
"listbox" CTRL_LISTBOX
"progressbar" CTRL_PROGRESSBAR
"trackbar" CTRL_TRACKBAR
"combobox" CTRL_COMBOBOX
"newtoolbar" CTRL_NEWTOOLBAR
"menubutton" CTRL_MENUBUTTON
"propsheet" CTRL_PROPSHEET
"ScrollWnd" CTRL_SCROLLWND
"ScrollView" CTRL_SCROLLVIEW
"treeview" CTRL_TREEVIEW
"listview" CTRL_LISTVIEW
"MonthCalendar" CTRL_MONTHCALENDAR
"SpinBox" CTRL_SPINBOX
"CoolBar" CTRL_COOLBAR
"IconView" CTRL_ICONVIEW
"gridview" CTRL_GRIDVIEW
"Animation" CTRL_ANIMATION
调用CreateWindow/CreateWindowEx创建预定义控件类的实例
HWND GUIAPI CreateWindowEx(const char*spClassName,const char*spCaption,DWORD dwStyle,DWORD dwExStyle,int id,int x,int y,int w,int h,HWND hParentWnd,DWORD dwAddData);

BOOL GUIAPI DestroyWindow(HWND hWnd);

#define CreateWindow(class_name,caption,style,id,x,y,w,h,parent,add_data) CreateWindowEx(class_name,caption,style,0,id,x,y,w,h,parent,add_data) 
参数:
控件类,标题,风格,标识符,位置,父窗口,附加数据
例:
#define IDC_STATIC1 100
#define IDC_STATIC2 150
#define BUTTON1 110
#define BUTTON2 120
#define EDIT1 130
#define EDIT2 140
//创建一个静态框
hStaticWnd1=CreateWindow(CTRL_STATIC,"This is a static control",WS_CHILD|WS_VISIBLE|WS_BORDER|SS_NOTIFY|SS_SIMPLE,
IDC_STATIC1,
10,10,180,300,
hWnd,
0);
//在hStaticWnd1中创建两个按钮
hButton1=CreateWindow(CTRL_BUTTON,"button1",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
IDC_BUTTON1,
20,20,80,20,
hStaticWnd1,
0);

hButton2=CreateWindow(CTRL_BUTTON,"button2",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
IDC_BUTTON2,
20,50,80,20,
hStaticWnd1,
0);
//在hStaticWnd1中创建一个编辑框
hEdit1=CreateWindow(CTRL_EDIT,"edit box 1",
WS_CHILD|WS_VISIBLE|WS_BORDER,
IDC_EDIT1,
20,80,100,24,
hStaticWnd1,
0);
//在hStaticWnd1中创建一个静态框
hStaticWnd2=CreateWindow(CTRL_STAIC,"This is a child static control",
WS_CHILD|WS_VISIBLE|WS_BORDER|SS_NOTIFY|SS_SIMPLE,
IDC_STATIC2,
20,110,100,50,
hStaticWnd1,
0);
//在hStaticWnd2中创建一个编辑框(为hStaticWnd1的孙窗口)
hEdit2=CreateWindow(CTRL_EDIT,"edit box 2",
WS_CHILD|WS_VISIBLE|WS_BORDER,
IDC_EDIT2,
0,20,100,24,
hStaticWnd2,
0);
控件内部发生事件时,向父窗口发送MSG_COMMAND消息
该消息的wParam由子窗口标识符和通知码组成
lParam含有发出通知消息的控件句柄
如:
编辑框向父窗口发送EN_CHANGE消息
switch(message)
{
case MSG_COMMAND:
int id=LOWORD(wParam);
int nc=HIWORD(wParam);
if(id==ID_MYEDIT&&nc==EN_CHANGE)
{...
}
break;
}
设置控件通知消息回调函数
SetNotificationCallback
例:
编辑框的回调函数
static void notif_proc(HWND hwnd,int id,int nc,DWORD add_data)
当对话框中有多个控件时要分别定义每一个控件的回调函数
并在对话框初始话消息时设置
case MSG_INITDIALOG:
SetNotificationCallback(GetDlgItem(hDlg,IDC_SIZE_MM),notif_proc);
控件子类化,定制特殊的控件
#define IDC_CTRL1 100
#define IDC_CTRL2  110
#define IDC_CTRL3  120
#define IDC_CTRL4  130
#define MY_ES_DIGIT_ONLY 0x0001
#define MY_ES_ALPHA_ONLY 0x0002
staic WNDPROC old_edit_proc;

学习MiniGUI之窗口创建篇

分类: minigui2009-11-04 12:56
最近在学习MiniGui,将一些分析的结果贴出来供大家参考,同时欢迎大家的指正。

图形编程中,窗口是一个重要的概念,窗口其实是一个矩形框,应用程序可以使用其从而达到输出结果和接受用户输入的效果。窗口系统(Window System)界于操作系统层次之上,它是一个软件系统,负责把显示屏幕分隔为不同的部分来帮助用户管理和控制不同的显示环境,它提供基于窗口的工作模式。在Linux上面,X就是一个典型的窗口系统吧。

   在MiniGui中有三种窗口类型:主窗口,对话框和控件窗口。主窗口作为应用程序的主界面或开始界面。子窗口通常是控件窗口,也可以是自定义窗口类,这里的控件窗口说白了就是一些窗口上面的控件,比如按钮,编辑框等。对话框其实就是主窗口,只不过一般为了完成特殊用途,所以在此加以区分。

   下面我们一起来看看这三种窗口类型的创建吧。首先看CreateMainWindow函数,它创建一个主窗口:由于代码比较长,这里就不全部贴出了,主要是说说关键的部分。

   CreateMainWindow函数通过接受PMAINWINCREATE类型的参数而创建一个窗口,并返回其句柄。关于PMAINWINCREATE结构的具体成员变量,大家可以去查看源码。下面主要对函数内部做个简单介绍。

1.       声明一个PMAINWIN类型,并分配空间,该变量用来存放创建的主窗口的信息

2.       说下面的代码之前,先说说托管(Hosting)窗口和被托管(Hosted)窗口吧。我们知道MiniGui内部实现了消息机制,即当有键盘输入事件发生时,就往消息队列中发送键盘消息,而一般是主窗口会不停的从消息队列中取出消息来处理,或者自己响应,或者忽略,或者派发给其他的窗口。那么这里就有一个问题,消息队列是每个主窗口都有一个呢,还是所有的主窗口都使用同一个消息队列?在MiniGui中有个特殊的主窗口HWND_DESKTOP,它是所有窗口的父窗口,直观的说就是整个桌面的窗口。当一个主窗口在创建的时候,可以指定新建一个消息队列,也可以使用别的主窗口的消息队列,如果是后者,假设主窗口A在创建时指定使用主窗口B的消息队列,那么A就被称为被托管窗口,而B则被称为托管窗口。所以很明显CreateInfo.hHosting就是用来指明托管窗口的。来看下面的代码,这里对MiniGUI的两种运行模式进行了区分,1-15行是MiniGUI-Threads模式,在这种模式下,如果托管窗口为HWND_DESKTOP,则新建一个消息队列(2-12行);如果托管窗口不为HWND_DESKTOP,则返回hHosting所在的主窗口的消息队列。16行是非MiniGUI-Threads模式下,仅仅表明新的主窗口使用HWND_DESKTOP的消息队列,这里其实忽略了pHosting参数。

1: #ifndef _LITE_VERSION

2:   if (pCreateInfo->hHosting == HWND_DESKTOP) {

3:        // Create message queue for this new main window.

4:        if( !(pWin->pMessages = malloc(sizeof(MSGQUEUE))) ) {

5:            free(pWin);

6:            return HWND_INVALID;

7:        }

8:     

9:        // Init message queue.

10:        if (!InitMsgQueue(pWin->pMessages, 0))

11:            goto err;

12:    }

13:    else

14:        pWin->pMessages = GetMsgQueue (pCreateInfo->hHosting);

15: #else

16:        pWin->pMessages = &__mg_dsk_msgs;

17: #endif
 

3.       下面的几行是对pWin进行初始化的操作,第1行赋值消息处理回调函数。第9行,初始化pZorderNode成员

1:    pWin->MainWindowProc = pCreateInfo->MainWindowProc;

2:    pWin->iBkColor    = pCreateInfo->iBkColor;

3:

4:    pWin->pCaretInfo = NULL;

5:

6:    pWin->dwAddData = pCreateInfo->dwAddData;

7:    pWin->dwAddData2 = 0;

8:

9:    if ( !( pWin->pZOrderNode = malloc (sizeof(ZORDERNODE))) )

10:        goto err;
 

4.       初始化结束之后,就开始发送消息通知自身来真正的绘制窗口了。1-4行发送本窗口的MSG_SIZECHANGING和MSG_CHANGESIZE消息,会调用本窗口消息回调函数中的相应处理部分。第6行是发送MSG_ADDNEWMAINWIN消息给HWND_DESKTOP窗口,HWND_DESKTOP窗口主要负责初始化Clip区和Invalid区,并且把当前窗口添加到sg_MainWinZOrder链表里,这个链表记录的是所有窗口的叠加顺序,在显示和隐藏窗口的时候,叠加顺序很重要,它会决定屏幕上哪些窗口会受影响而需要重绘。第9行发送MSG_CREATE消息给窗口,窗口接受到此消息一般进行子窗口的初始化和创建,如果创建失败了,则通知HWND_DESKTOP窗口销毁该主窗口。

1:  SendMessage ((HWND)pWin, MSG_SIZECHANGING,

2:                (WPARAM)&pCreateInfo->lx, (LPARAM)&pWin->left);

3:  SendMessage ((HWND)pWin, MSG_CHANGESIZE,

4:                (WPARAM)&pWin->left, 0);

5:

6:  SendMessage (HWND_DESKTOP, MSG_ADDNEWMAINWIN,

7:                (WPARAM) pWin, (LPARAM) pWin->pZOrderNode);

8:

9:  if (SendMessage ((HWND)pWin, MSG_CREATE, 0, (LPARAM)pCreateInfo)) {

10:        SendMessage(HWND_DESKTOP,

11:                      MSG_REMOVEMAINWIN, (WPARAM)pWin, 0);

12:        goto err;

13: }
 

 

接下来我们看对话框的创建过程,对话框分为模态和非模态对话框。非模态对话框的创建过程和主窗口的创建过程差不多,其中也调用了CreateMainWindow函数,之后还调用了CreateWindowEx创建对话框上的控件。模态对话框就是显示之后,用户不能再切换到其他主窗口进行工作的对话框,而只能在关闭之后,才能使用其他的主窗口,通过DialogBoxIndirectParam创建,一开始的步骤与非模态对话框类似,以下的代码是其不同的部分:第7行,hOwner是待创建对话框的托管主窗口,这里其实是把它disable掉了。第11行是处理MSG_INITDIALOG消息。第18-21行,是消息处理的循环机制,这里可以看到这就是为什么模态对话框一定要等到关闭之后,才可以使用其它的主窗口,这里还需要注意一点,由于是从对话框的托管主窗口是HWND_DESKTOP窗口,因此他们共用一个消息队列,此时,对话框可能接受到发送给托管主窗口的消息,而由于在第7行中已经将托管主窗口的dwStyle设置为WS_DISABLE了,因此在这些消息处理流程里面可以做相应的处理(例如当窗口被设置为WS_DISABLE时,忽略该消息)。25-28行,当窗口关闭时,进行的收尾工作。第31行enable托管主窗口。第23行判断了当前对话框是否是激活窗口,如果是的话,当它关闭时,它的托管主窗口应该被激活(34-35L)。

1:    hDlg = CreateMainWindow (&CreateInfo);

2:    if (hDlg == HWND_INVALID)

3:        return -1;

4:

5:    SetWindowAdditionalData2 (hDlg, (DWORD)(&retCode));

6:

7:    if (hOwner)

8:        EnableWindow (hOwner, FALSE);

9:  

10:    hFocus = GetNextDlgTabItem (hDlg, (HWND)0, FALSE);

11:    if (SendMessage (hDlg, MSG_INITDIALOG, hFocus, lParam)) {

12:        if (hFocus)

13:            SetFocus (hFocus);

14:    }

15:  

16:    ShowWindow (hDlg, SW_SHOWNORMAL);

17:  

18:    while( GetMessage (&Msg, hDlg) ) {

19:        TranslateMessage (&Msg);

20:        DispatchMessage (&Msg);

21:    }

22:

23:    isActive = (GetActiveWindow() == hDlg);

24:

25:    dlgDestroyAllControls (hDlg);

26:    DestroyMainWindow (hDlg);

27:    ThrowAwayMessages (hDlg);

28:    MainWindowThreadCleanup (hDlg);

29:  

30:    if (hOwner) {

31:        EnableWindow (hOwner, TRUE);

32:        if(isActive)

33:        {

34:            ShowWindow (hOwner, SW_SHOWNORMAL);

35:            SetActiveWindow (hOwner);

36:        }

37:    }

38:

39:    return retCode;
 

 

最后说一下子窗口(即控件)的创建过程。在MiniGUI中通过调用CreateWindow函数(CreateWindow其实是CreateWindowEx函数的宏)可以建立某个控件。控件的创建需要一个PCONTROL结构变量,下面这段代码中的第1行获取控件的主窗口。第4行通过向HWND_DESKTOP发送MSG_GETCTRLCLASSINFO,接受到消息之后会调用GetControlClassInfo函数根据传入的spClassName来获取控件的class info。控件的class info包括控件名称,默认的风格和扩展风格,消息回调函数等。后续的代码设置控件的属性。

1:   if (!(pMainWin = GetMainWindowPtrOfControl (hParentWnd)))

2:            return HWND_INVALID;

3:

4:   cci = (PCTRLCLASSINFO)SendMessage (HWND_DESKTOP,

5:            MSG_GETCTRLCLASSINFO, 0, (LPARAM)spClassName);

6:    if (!cci) return HWND_INVALID;

7:

8:    pNewCtrl = calloc (1, sizeof (CONTROL));

9:

10:    if (!pNewCtrl) return HWND_INVALID;

11:

12:    pNewCtrl->DataType = TYPE_HWND;

13:    pNewCtrl->WinType  = TYPE_CONTROL;

14:

15:    pNewCtrl->left     = x;

16:    pNewCtrl->top      = y;

17:    pNewCtrl->right    = x + w;

18:    pNewCtrl->bottom   = y + h;

        ……
 

设置完控件的属性之后,向HWND_DESKTOP发送MSG_NEWCTRLINSTANCE消息,HWND_DESKTOP接受到之后,会调用dskOnNewCtrlInstance函数创建控件,将它添加到其父窗口的children链表中(1L)。第16-18行判断是否可见,可见的话,就更新窗口显示它。

1: SendMessage (HWND_DESKTOP, MSG_NEWCTRLINSTANCE,

2:                (WPARAM)hParentWnd, (LPARAM)pNewCtrl);

3:

4: if (SendMessage ((HWND)pNewCtrl, MSG_CREATE,

5:                   (WPARAM)hParentWnd, (LPARAM)dwAddData)) {

6:       SendMessage (HWND_DESKTOP,

7:                      MSG_REMOVECTRLINSTANCE,

8:                      (WPARAM)hParentWnd, (LPARAM)pNewCtrl);

9:       goto error;

10:}

11: SendMessage ((HWND)pNewCtrl, MSG_SIZECHANGING,

12:                 (WPARAM)&rcExpect, (LPARAM)&pNewCtrl->left);

13: SendMessage ((HWND)pNewCtrl, MSG_CHANGESIZE,

14:                 (WPARAM)(&pNewCtrl->left), 0);

15:

16: if (pNewCtrl->pParent->dwStyle & WS_VISIBLE && pNewCtrl->dwStyle &

17:     WS_VISIBLE)

18:       UpdateWindow ((HWND)pNewCtrl, TRUE);
 

你可能感兴趣的:(MINIGUI)