第八章 鼠标(CHECKEENVISION壹)

CHECKE兰德酷路泽1程序将客户细分分为二三个矩形,构成三个伍*5的数组。假如在内部1个矩形内单击鼠标,就用X形填充该矩形。再一次单击,则X形消失。

     前面包车型地铁壹篇文章里面,作者模仿那本杰出的书写了四个windows程序,
对windows的顺序设计有了一丝丝的感到认识,
然而对于程序的规划仍然管中窥豹,由此须要后续自学,
接着看那本精华的书……

深信不疑读者朋友们对OFFICE3000必将特别熟知吧,它当中的东东可真不少,不管是活泼可爱的”大眼夹”,照旧各个平面造型的Windows控件都十分受广大用户喜爱。那么这一次就让我们来模拟它做个尤其常用的控件:”颜色组合框”。要是你今后正在做关于字管理类的软件时这些”东东”一定对您有用。程序编写翻译运营后的分界面效果如图1所示:

1、相关类

图片 1图片 2

     上面是自作者的一点总计吧,贴出来让各位壮士看看,希望英豪们请教,
提议自己认知中的不当之处,以协理笔者在自习的长河中增进…….

图一、颜色选择组合框

  CStatusBar 
-父类CControlBar,封装了关于状态栏的操作,也包涵状态栏的创导

  1 /*--------------------------------------------
  2 CHECKER1.C -- Mouse Hit-Test Demo Program No.1
  3               (c) Charles Petzold, 1998
  4 --------------------------------------------*/
  5 
  6 #include <Windows.h>
  7 
  8 #define DIVISION 5
  9 
 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 11 
 12 int WINAPI WinMain( __in HINSTANCE hInstance
 13                     , __in_opt HINSTANCE hPrevInstance
 14                     , __in LPSTR lpCmdLine
 15                     , __in int nShowCmd )
 16 {
 17     static TCHAR szAppName[] = TEXT("Checker1");
 18     HWND hwnd;
 19     MSG msg;
 20     WNDCLASS wndclass;
 21 
 22     wndclass.style = CS_HREDRAW | CS_VREDRAW;
 23     wndclass.lpfnWndProc = WndProc;
 24     wndclass.cbClsExtra = 0;
 25     wndclass.cbWndExtra = 0;
 26     wndclass.hInstance = hInstance;
 27     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 28     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
 29     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 30     wndclass.lpszMenuName = NULL;
 31     wndclass.lpszClassName = szAppName;
 32 
 33     if (!RegisterClass(&wndclass))
 34     {
 35         MessageBox(NULL, TEXT("Program requires Windows NT!")
 36             , szAppName, MB_ICONERROR);
 37         return 0;
 38     }
 39 
 40     hwnd = CreateWindow(szAppName, TEXT("Checker1 Mouse Hit-Test Demo")
 41         , WS_OVERLAPPEDWINDOW
 42         , CW_USEDEFAULT, CW_USEDEFAULT
 43         , CW_USEDEFAULT, CW_USEDEFAULT
 44         , NULL, NULL, hInstance, NULL);
 45 
 46     ShowWindow(hwnd, nShowCmd);
 47     UpdateWindow(hwnd);
 48 
 49     while (GetMessage(&msg, NULL, 0, 0))
 50     {
 51         TranslateMessage(&msg);
 52         DispatchMessage(&msg);
 53     }
 54 
 55     return msg.wParam;
 56 }
 57 
 58 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 59 {
 60     static BOOL fState[DIVISION][DIVISION];
 61     static int cxBlock, cyBlock;
 62     HDC hdc;
 63     int x, y;
 64     PAINTSTRUCT ps;
 65     RECT rect;
 66 
 67     switch (message)
 68     {
 69     case WM_SIZE:
 70         cxBlock = LOWORD(lParam) / DIVISION;
 71         cyBlock = HIWORD(lParam) / DIVISION;
 72         return 0;
 73 
 74     case WM_LBUTTONDOWN:
 75         x = LOWORD(lParam) / cxBlock;
 76         y = HIWORD(lParam) / cyBlock;
 77 
 78         if (x < DIVISION && y < DIVISION)
 79         {
 80             fState[x][y] ^= 1;
 81 
 82             rect.left = x * cxBlock;
 83             rect.top = y * cyBlock;
 84             rect.right = (x + 1) * cxBlock;
 85             rect.bottom = (y + 1) * cyBlock;
 86 
 87             InvalidateRect(hwnd, &rect, FALSE);
 88         }
 89         else
 90             MessageBeep(0);
 91         return 0;
 92 
 93     case WM_PAINT:
 94         hdc = BeginPaint(hwnd, &ps);
 95 
 96         for (x = 0; x < DIVISION; ++x)
 97             for (y = 0; y < DIVISION; ++y)
 98             {
 99                 Rectangle(hdc, x * cxBlock, y * cyBlock
100                     , (x + 1) * cxBlock, (y + 1) * cyBlock);
101 
102                 if (fState[x][y])
103                 {
104                     MoveToEx(hdc, x * cxBlock, y * cyBlock, NULL);
105                     LineTo(hdc, (x + 1) * cxBlock, (y + 1) * cyBlock);
106                     MoveToEx(hdc, x * cxBlock, (y + 1) * cyBlock, NULL);
107                     LineTo(hdc, (x + 1) * cxBlock, y * cyBlock);
108                 }
109             }
110 
111         EndPaint(hwnd, &ps);
112         return 0;
113 
114     case WM_DESTROY:
115         PostQuitMessage(0);
116         return 0;
117     }
118 
119     return DefWindowProc(hwnd, message, wParam, lParam);
120 }

     哈哈哈……….

  一、达成形式

2、状态栏的应用

CHECKER1.C

四.一   展现和换代
windows应用程序的展现区域:
      
除标题栏、应用程序边框、菜单栏、工具栏、滚动条和气象条外的连串分配给应用程序的窗口区域。
Windows展现文字和图纸的情势:
       一、通过绘制应用程序的来得区域来贯彻
      
贰、当应用程序的一些部分被覆盖后,windows不会保留被遮住的区域,当程序移开后,windows通过发送音信文告
            应用程序必要重新绘制被遮住的区域来兑现展现
      
三、windows通过发送WM_PAINT音讯来打招呼应用程序的窗口新闻处理程序,需求重新绘制展现区域
4.2  WM_PAINT消息:
  WM_PAINT新闻的产生时机:
      
一、在调用UpdateWindow函数时,windows会像应用程序发送3个WM_PAINT新闻,通告应用程序必要重绘呈现区域。
       贰、在应用程序的使用者移动窗口时,窗口中先前被隐形的区域重新可知
       三、使用者更改窗口的大小,同时wndclass.style 中设定了CS_VREDRAW
和CS_HREDRAW
       4、程序中调用ScrollWindow或ScrollDC函数滚动展现区域的壹某些
       伍、程序中运用InvalidateRect或Invalidate奇骏gn函数产生WM_PAINT消息

  首先让大家先来打探一下画控件的基本原理和经过,或许那些才是本文的本心。我们都掌握Windows中颇具可视的东西都以画出来的,那么这几个画画的在那之中进度又是怎么样的呢?一般画Windows控件的历程分成三大多数:壹是在WM_MEASUREITEM音信影射函数中设置当前要画的Item的轻重尺寸;二是在WM_DRAWITEM音讯影射函数中遵照Item的大大小小尺寸来画该Item(Logo/位图/字符串等);3是在WM_PAINT音讯映射函数中持续的绘图当前的控件内容。

  二.一开立状态栏 CStatusBar::CreateEx / CStatusBar::Create

CHECKEKuga一程序呈现结果如图所示:

 可能爆发WM_PAINT的时机:
       1、Windows擦除了覆盖应用程序的对话框恐怕音信框
       贰、菜单下拉下拉后然后被释放
       三、突显ToolTip提醒消息后
   以下意况Windows通过保存音信来过来显示区域
       一、鼠标的光标穿越展现区域
       贰、Logo拖过展现区域
   管理进度:
     
应用程序保留重新绘制突显区域的全部新闻,并且当接到到WM_PAINT音信时展开始展览示区域的重新绘制可能第三制图(UpdateWindow时)
4.叁 无效矩形和立见成效矩形
   无效矩形:
      
一、应用程序的显得区域中被掩盖的区域正是不行矩形区域。无效矩形也称作无效区域。
      
2、就是因为无效矩形的存在才使Windows发送WM_PAINT音信给应用程序,只有在浮现区域的某一片段失效后应用程序窗口才会接受WM_PAINT消息
   绘图新闻结构:
       一、 windows内部为每1个窗口保存2个制图音讯结构,
这一个组织包罗了重围无效区域的细小矩形的坐标以及别的音信
       二、假若在应用程序管理WM_PAINT新闻在此以前,
展现区域的另三个区域成为无效,则windows会总结出一个饱含多少个区域的新的不算区域,并将那种变化音讯保存在绘图消息结构
       三、windows不会将多少个WM_PAINT消息放到音信对列
   InvalideateRect函数
      
1、窗口语资源新闻息管理程序能够透过呼叫InvalidateRectangular使显示区域内的矩形无效
      
二、调用InvalidateRect函数时要是音讯队列中早已存在WM_PAINT,即现已存在无效区域,windows将总结新的无效区域。假使音讯队列无WM_PAINT则将
          一个WM_PAINT音讯投递到音讯队列。
      
三、在接到到WM_PAINT新闻时,窗口处理程序/函数能够获得无效区域的坐标。
       4、在任何时刻能够经过呼叫GetUpdateRect获得无效区域的坐标
   Tip:
      
在处理WM_PAINT消息时,窗口语资源新闻息处理程序在呼叫BeginPaint之后1切区域立即产生有效,
程序也得以透过呼叫ValidateRect函数使彰显区域内的放肆矩形都改为有效。
      
假诺呼叫具有令全部突显区域改为有效的功力,则当前音信队列中的WM_PAINT都将被去除。
4、4 GDI
   GDI:
        要在窗口显示区域绘图,能够行使windows的图像设备接口:GDI
   文字绘制:
        1、DrawText函数
        2、TextOut函数
           原型: TextOut(HDC hdc, int x, int y,char *psText,int
iLength);
           hdc: 设备内容句柄
           x:呈现文字开头的x坐标
           y: 展现文字起初的y坐标
           psText: 指向要呈现的字符串的指针
           iLength: 待突显字符串的长度
   设备内容:
       壹、设备内容句柄是GDI函数的通行证,通过配备内容句柄,
程序就足以在彰显区域上制图。
       二、设备内容 DC:
是GDI内部保存的数据结构,设备内容与一定的浮现设备相关。对于系统桌面,
设备内容总是与显示屏上的一定窗口相关
      
3、设备内容中某个值是图片属性,那一个属性定义了GDI绘图函数的底细。
   通过设备内容绘图的历程:
      
一、程序须要绘图时,必须取得设备内容句柄,在取得该句柄后,windows系统用钦定的属性值填入个中设施内容结构
       二、能够呼叫分歧的GDI函数获取道具内容的属性值
       三、能够呼叫GDI函数退换设备内容的属性值
       4、利用其余GDI函数在展现区域绘图
       五、当程序在展现区域绘图落成后,必须自由设备内容句柄,
被放出的句柄不可能再被运用
       陆、程序必须在管理单个新闻管理时期得到和自由设备内容句柄。
       Tip:
        
除了呼叫CreateDC建立的设备内容外,程序不可能在四个音信之间保存其余装置内容句柄。
   获取器具内容句柄:  
   方法一:处理WM_PAINT新闻时利用
       1、BeginPaint和EndPaint函数
           
BeginPaint和EndPaint函数需求窗口句柄(在windows呼叫应用程序窗口管理函数时,作为参数字传送递给应用程序窗口管理函数)
          和PAINTSTRUCT结构的地点作为参数。
            BeginPaint函数再次回到多少个与窗口相关联的装置内容句柄。
           其原型如下:
                        HDC  BeginPaint(HWND, PAINTSTRUCT *)
          
而EndPaint函数释放由BeginPaint函数取得的装置内容句柄,其原型如下:
                             EndPaint(HWND, PAINTSTURCT *)
       2、WM_PAINT音信管理进度
          PreStep:
                  HDC hdc;
                  PAINTSTRUCT  ps;
          step一:
首先呼叫BeginPaint函数获得1个与窗口相关联的配备内容句柄;
                  hdc=BeginPaint(hwnd,&ps);
          Step二:  使用GDI函数实行绘图;
          Step3: 释放由BeginPaint函数取得设备内容句柄:
                  EndPaint(hwnd,&ps);
          EndStep: return
0;//在每二个新闻管理完后,均要求重临到windows系统,并且只要成功施行窗口回调函数则赶回0.
       3、WM_PAINT音信处理组织:
            case WM_PAINT:
                     hdc=BeginPaint(hwnd,&ps);
                     call other GDI function
                     EndPaint(hwnd,&ps);
                     return 0;
       4、
假若在窗口音讯管理函数中不管理WM_PAINT音信,则必须将WM_PAINT音讯传递给DefWindowProc函数进行处理,DefWindowProc函
           数以下边的代码管理WM_PAINT消息:
            case WM_PAINT:
                 BeginPaint(hwnd,&ps);
                 EndPaint(hwnd,&ps);
                 return 0;
           表明以下DefWindowProc的原型:
                  DefWindowProc(HWND,
MSG,WPARAM,LPARAM);//与窗口音讯管理函数基本同样的构造
       5、windows产生WM_PAINT音讯是因为体现区域的有个别区间产生无效,
借使不呼叫BeginPaint和EndPaint,大概ValidateRect,则windows
        
不会是于事无补区域成为有效,相反windows会发送另2个WM_PAINT音讯,且从来发送过去。 
   绘图新闻结构  PAINTSTRUCT:
       一、绘图消息结构定义:
              typedef struct tagPAINTSTRUCT
                {
                     HDC   hdc;   //设备内容句柄
                     BOOL  f伊拉斯e;  //是还是不是曾经擦除无效矩形的背景
                     RECT  rcPaint;
                     BOOL  fRestore;
                     BOOL  fIncUpdate;
                     BYTE  rgbReserved[32];
                 }PAINTSTRUCT;
        2、windows 呼叫
             
在先后呼叫BeginPaint函数时,windows会将该组织的各种成员填充好,应用程序只行使前八个字段,其余由windows内部接纳。
          
呼叫BeginPaint函数时填充ps.f伊拉斯e字段来代表是不是早已擦除无效区域的背景:
                  ps.f伊拉斯e = FALSE (0)
则代表早已擦除无效区域背景;同时windows会采纳wndclass.hbrBcakground钦命的画刷来擦除背景。

    BOOL CreateEx(

图片 3

       
三、假如程序呼叫InvalidateRect使展现区域中的矩形失效,则InvalidateRect函数的终极二个参数会钦点是或不是擦除背景。如若那些参数为FALSE
           则windows不会擦除背景,并且在呼唤完BeginPaint后将置
ps.f伊拉斯e=TRUE 非零。
          
在处理WM_PAINT音讯时,假若必要在低效区域外拓展重绘,能够呼叫InvalidateRect函数:
            Exp:
                 InvalidateRect(hwnd,NULL,TRUE);
           
在BeginPaint函数在此之前呼叫InvalidateRect函数使全数显示区域改为无效,并擦除背景;但1旦最终贰个参数等于FALSE,则不会擦除背景,窗口
            中本来的消息还保存在原处。
        肆、RECT rcPaint 是五个RECT型的结构体,
PAINTSTRUCT结构中的rcPaint成员定义了没用区域的分界。

上面大家本着CBSColorComboBox类的那多少个进程来做个简易的介绍:

      CWnd* pParentWnd, 
//内定状态栏的父窗口指针,平常都以指向程序的框架类窗口对象

装有二四个矩形具备一样的增进率和中度,这几个宽度和惊人被封存在cxBlock、cyBlock中。无论几时转移客户区的深浅,程序都将再一次总计cxBlock、cyBlock。WM_LBUTTONDOWN管理逻辑利用鼠标的坐标来决断哪些矩形被单击,然后在fState数组中使用位运算符(按位异或^)计算这个矩形的新情景,最终强制使该矩形失效,从而发生WM_PAINT消息。

前方的剧情大概的叙说了选择BeginPaint和EndPaint函数来拍卖WM_PAINT音信的建制,精晓不完了的地点请各位见谅。

  在WM_MEASUREITEM音讯影射函数中设定Item的轻重缓急尺寸的时候,大家只需求设置Item的万丈就可以。那里的万丈大家设置为2倍的系统小Logo(SMALL
ICON)的莫斯中国科学技术大学学,其尺寸用::GetSystemMetrics(SM_CXSMICON)取得。

      DWO大切诺基D dwCtrlStyle = 0 , 
//设置内嵌在情景栏上的CStatusBarCtrl对象创立时的壮狂风格

设若客户区的幅度和可观不可能被5整除,客户区的左侧或底层就会油不过生1个小长条区域,不被实行覆盖。在那片区域开始展览鼠标单击时,CHECKE途乐一程序会调用MessageBeep函数举行响应。

    下边包车型地铁有的函数的原型未有指明重临值类型,
大家能够由此编写翻译境遇要好查看, 因为作者有点懒,所以就没查看了。

  Visual
C++的先后开辟人士能够在Item的矩形区域内画五花八门的新闻,比如:Logo/位图/字符串等等。那么有人会疑窦:”大家用什么样来画?大家在哪里画?又怎么来画吗?”。答案其实都在那么些LPDRAWITEMSTRUCT结构中。hDC成员为道具上下文遭遇(HDC),获得了该器械句柄也就代表大家有着了画任何位图/Logo/文本的本事;那么接下去的主题素材即是:我们在哪儿来画吗?答案也很简短:获得LPDRAWITEMSTRUCT结构中Item的矩形区域(rcItem),那么那正是您施展才华的空间了,要充裕利用它哦!

      DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
//状态栏的风格

当CHECKERubicon1程序收到WM_PAINT音信时,它会再一次绘制整个客户区,利用GDI中的Rectangle函数画出富有的矩形。若fState值为真,则CHECKERubicon1程序调用函数MoveToEx和函数LineTo函数画出两条直线。

    哈哈哈哈…………….原来windows下的程序设计有C的功底,加上学习一大堆windows定义各类API函数,
加上有的运维机制的明白,即使是生手级的不入门的主次编制程序职员(就像是自个儿一般)也能完成一个简短的应用………………..

  最终一步便是何等来画的标题了,说白了正是何许分配每一种成分的长空,怎么样在它们各自的长空上画出你想要的事物。依据符合规律一般分别计算出ICON所占的矩形区域/文本所占的矩形区域/位图的矩形区域,倘若您还有任何因素那么也相应总计出该因素所占的矩形区域/位图所占的矩形区域。接下来的上上下下都很轻松了,不外乎CDC类的多少个常用函数:画Logo用DrawIcon()、画位图用BitBlt()、画文字用DrawText()等函数。要是你感觉视觉上还不够老板L,你还足以来设置各样Item的文本颜色,背景颜色,以及Logo的勃兴和凹陷的视觉效果。

      UINT nID = AFX_IDW_STATUS_BA库罗德  
//钦命状态栏这一个子窗口的ID,私下认可为AFX_IDW_STATUS_BAR

    我发觉用LiveWrite这几个东西相比较好…….

  不过在上述进程中须要小心八个难题,1是为了破除不断绘制所推动的闪光现象,须要在WM_ERASEBKGND新闻响应中作些特殊管理;在WM_PAINT新闻中一向把组合框的客户区当成1幅位图来不断更新,而不是对ICON区域和文件区域分别重绘。2是每当用户退换了组合框的此时此刻内容后,在画新的Item以前一定要记得清除前次组合框内的剧情。三是假设想选择愈多的水彩,那么1旦选取组合框中的最终二个Item(More
Colors)就可以,这一个Item是为用户自定义颜色而特别设置的。

    );

  贰、编制程序步骤

    BOOL Create(

  1、运维Visual
C++6.0,生成一个基于对话框的档期的顺序,将该类型命名字为”WW”;

      CWnd* pParentWnd, 
//钦命状态栏的父窗口指针,平时都是指向程序的框架类窗口对象

  2、使用Class
Wizard新建一个类CBSColorComboBox,其基类采用为CComboBox类;

      DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
//状态栏的品格

  3、在先后的对话框中放置一个ComboBox控件,使用CLASSWIZA卡宴D加多相应的CComboBox类成员变量,然后将该成员变量的品种修改为CBSColorComboBox;

      UINT nID = AFX_IDW_STATUS_BA奇骏 
//钦赐状态栏那个子窗口的ID,默以为AFX_IDW_STATUS_BAR

  4、加多代码,编写翻译运转程序。

    );

**三、程序代码

    在先后的CMainFrame类的OnCreate函数中可知MFC自动创设状态栏的主意:      

**

if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(
    indicators,sizeof(indicators)/sizeof(UINT)))
{
    TRACE0("Failed to create status bar\n");
    return -1;      // fail to create
}
//////////////////////////////////////////////////////////////CBSColorComboBox类的头文件;
#if !defined(_BS_BSCOLORCB)
#define _BS_BSCOLORCB
#include <afxtempl.h>
//系统常用颜色的自定义名称
const static char* strColorName[] =
{
 "crSCROLLBAR","crBACKGROUND","crACTIVECAPTION", "crINACTIVECAPTION", "crMENU", "crWINDOW", "crWINDOWFRAME",  "crMENUTEXT", "crWINDOWTEXT", "crCAPTIONTEXT", "crACTIVEBORDER","crINACTIVEBORDER", "crAPPWORKSPACE",  "crHIGHLIGHT", "crHIGHLIGHTTEXT", "crBTNFACE", "crBTNSHADOW", "crGRAYTEXT", "crBTNTEXT",  "crINACTIVECAPTIONTEXT",
 "crBTNHIGHLIGHT","cr3DDKSHADOW", "cr3DLIGHT", "crINFOTEXT", "crINFOBK",
 "crHOTLIGHT","crGRADIENTACTIVECAPTION", crGRADIENTINACTIVECAPTION"
};

typedef struct BSCBITEM
{
 int iIndex;
 COLORREF crColor;
 LPCTSTR lpCaption;
}BSCBITEM, *LPBSCBITEM;

class CBSColorComboBox : public CComboBox
{
 DECLARE_DYNCREATE(CBSColorComboBox)
 public:
  CBSColorComboBox();
  virtual ~CBSColorComboBox();
  BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
  //初始化组合框(第一个被调用的函数)
  void InitBSColorCB(void);
  //得到当前的颜色值或R/G/B值
  COLORREF GetColor();
  void GetRGBValue(int* R, int* G, int* B);
 public:
  //{{AFX_VIRTUAL(CBSColorComboBox)
   public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
  //}}AFX_VIRTUAL
 protected:
  bool m_bOverControl; //鼠标的状态(是否处于按钮上)
  int iIconX, iIconY; //SMALL ICON的大小尺寸
  COLORREF m_crColor; //当前选中的颜色
  CList<LPBSCBITEM, LPBSCBITEM> m_crItem;

  void OnCBPaint(CDC* pDC);
  LPBSCBITEM GetItem(int iIndex = 0);
 protected:
  //{{AFX_MSG(CBSColorComboBox)
   afx_msg BOOL OnEraseBkgnd(CDC* pDC);
   afx_msg void OnPaint();
   afx_msg void OnTimer(UINT nIDEvent);
   afx_msg void OnMouseMove(UINT nFlags, CPoint point);
   afx_msg void OnSelchange();
   afx_msg void OnSelendok();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};
#endif // !defined(_BS_BSCOLORCB)

///////////////////////////////////////////////////////////////CBSColorComboBox的实现文件;
#include "stdafx.h"
#include "BSColorComboBox.h"
CBSColorComboBox::CBSColorComboBox()
{
 //当前鼠标是否在对象上
 m_bOverControl = false;
 //小图标尺寸
 iIconX = ::GetSystemMetrics(SM_CXSMICON);
 iIconY = ::GetSystemMetrics(SM_CYSMICON);
}

CBSColorComboBox::~CBSColorComboBox()
{
 while(!m_crItem.IsEmpty())
 {
  LPBSCBITEM lpItem = m_crItem.RemoveHead();
  delete lpItem;
 }
}

BOOL CBSColorComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
 DWORD dw = dwStyle;

 if( !CComboBox::Create(dw, rect, pParentWnd, nID) )
  return false;
 CFont * font = CFont::FromHandle((HFONT)::GetStockObject(DEFAULT_GUI_FONT));
 SetFont(font);

 return true;
}
IMPLEMENT_DYNCREATE(CBSColorComboBox, CComboBox)

BEGIN_MESSAGE_MAP(CBSColorComboBox, CComboBox)
//{{AFX_MSG_MAP(CBSColorComboBox)
 ON_WM_ERASEBKGND()
 ON_WM_PAINT()
 ON_WM_TIMER()
 ON_WM_MOUSEMOVE()
 ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelchange)
 ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendok)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CBSColorComboBox::InitBSColorCB(void)
{
 int iMinColor = COLOR_SCROLLBAR,
 iMaxColor = COLOR_BTNHIGHLIGHT;
 if(WINVER >= 0x0400)
  iMaxColor = COLOR_INFOBK;
 if(WINVER >= 0x0500)
  iMaxColor = 28;
 //初始化CB颜色列表框的Item(常见的SysColor值)
 for(int iLoop = iMinColor; iLoop <= iMaxColor; ++iLoop)
 {
  LPBSCBITEM lpItem = new BSCBITEM;
  lpItem->iIndex = AddString(strColorName[iLoop]);
  lpItem->crColor = ::GetSysColor(iLoop);
  lpItem->lpCaption = strColorName[iLoop];
  //
  if(m_crItem.IsEmpty())
   m_crItem.AddHead(lpItem);
  else
   m_crItem.AddTail(lpItem);
 }
 //该Item是为了用户自定义颜色而设置
 LPBSCBITEM lpItem = n

      SetIndicators函数的率先个参数indicators为二个静态数组,其定义在CMainFrame类的源文件中:

        static UINT indicators[] =

        {

              ID_SEPARATOR,       //提示行

              ID_INDICATOR_CAPS,  //Caps Lock键的意况提醒器

              ID_INDICATOR_NUM,   //Num Lock键的意况提醒器

              ID_INDICATOR_SC中华VL,  //Scroll Lock键的事态提醒器

        };

        该数组中的后2个ID都以MFC预先定义好的字符串财富ID,在工程的财富窗口中的String
Table的字串表中可知:

          图片 4

发表评论

电子邮件地址不会被公开。 必填项已用*标注