列表框 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 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); |