应用程序中贯彻颜色挑选组合框

by admin on 2019年3月25日

CHECKE安德拉1程序将客户细分分为2四个矩形,构成1个5*5的数组。即使在里面一个矩形内单击鼠标,就用X形填充该矩形。再一次单击,则X形消失。

     前边的一篇小说里面,笔者模仿那本草从新典的书写了七个windows程序,
对windows的次第设计有了一丝丝的神志认识,
但是对于程序的布置如故夏虫语冰,因而须求一连自学,
接着看那黄帝内经典的书……

信任读者对象们对OFFICE三千毫无疑问十三分熟悉吧,它里面包车型地铁东东可真不少,不管是活泼可爱的”大眼夹”,依然各个平面造型的Windows控件都很受周边用户喜好。那么本次就让大家来效仿它做个非平常用的控件:”颜色组合框”。假若您今后正在做关于字处理类的软件时这些”东东”一定对您有用。程序编写翻译运营后的界面效果如图一所示:

1、相关类

home88一必发 1home88一必发 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 }

     哈哈哈……….

  壹 、完毕方式

二 、状态栏的使用

CHECKER1.C

4.1   展现和立异
windows应用程序的显示区域:
      
除标题栏、应用程序边框、菜单栏、工具栏、滚动条和情形条外的系统一分配配给应用程序的窗口区域。
Windows彰显文字和图片的格局:
       一 、通过绘制应用程序的显得区域来促成
      
② 、当应用程序的一点部分被掩盖后,windows不会保留被覆盖的区域,当程序移开后,windows通过发送新闻布告
            应用程序供给再行绘制被覆盖的区域来贯彻呈现
      
③ 、windows通过发送WM_PAINT音信来打招呼应用程序的窗口音讯处理程序,供给再行绘制展现区域
应用程序中贯彻颜色挑选组合框。4.2  WM_PAINT消息:
  WM_PAINT消息的发生时机:
      
一 、在调用UpdateWindow函数时,windows会像应用程序发送三个WM_PAINT音信,布告应用程序需求重绘展现区域。
       贰 、在应用程序的使用者移动窗口时,窗口中先前被隐形的区域重新可知
       三 、使用者改变窗口的深浅,同时wndclass.style 中设定了CS_VREDRAW
和CS_HREDRAW
       ④ 、程序中调用ScrollWindow或ScrollDC函数滚动显示区域的一某些
       ⑤ 、程序中应用InvalidateRect或Invalidate奥迪Q5gn函数产生WM_PAINT消息

  首先让大家先来询问一下画控件的基本原理和进度,大概这一个才是本文的原意。大家都通晓Windows中享有可视的事物都是画出来的,那么这些画画的中间进度又是哪些的吧?一般画Windows控件的历程分成三大部分:一是在WM_MEASUREITEM新闻影射函数中安装当前要画的Item的大大小小尺寸;二是在WM_DRAWITEM新闻影射函数中根据Item的轻重尺寸来画该Item(图标/位图/字符串等);三是在WM_PAINT新闻映射函数中频频的绘图当前的控件内容。

  2.1创制状态栏 CStatusBar::CreateEx / CStatusBar::Create

CHECKE奥迪Q51程序展现结果如图所示:

 大概发生WM_PAINT的时机:
       ① 、Windows擦除了覆盖应用程序的对话框只怕音信框
       贰 、菜单下拉下拉后然后被保释
       叁 、突显ToolTip提醒消息后
   以下情况Windows通过保存消息来回复显示区域
       ① 、鼠标的光标穿越展现区域
       ② 、图标拖过呈现区域
   处理进度:
     
应用程序保留重新绘制展现区域的享有音信,并且当收到到WM_PAINT消息时开始展览展示区域的再一次绘制也许第二制图(UpdateWindow时)
4.3 无效矩形和实惠矩形
   无效矩形:
应用程序中贯彻颜色挑选组合框。      
一 、应用程序的展现区域中被遮住的区域正是不著见效矩形区域。无效矩形也称作无效区域。
      
② 、正是因为无效矩形的存在才使Windows发送WM_PAINT新闻给应用程序,只有在展示区域的某一部分失效后应用程序窗口才会吸收WM_PAINT消息
   绘图新闻结构:
       一 、 windows内部为每二个窗口保存三个绘制音讯结构,
这几个结构包罗了包围无效区域的细微矩形的坐标以及任何消息
       二 、假如在应用程序处理WM_PAINT音信此前,
呈现区域的另四个区域改为无效,则windows会计算出一个涵盖七个区域的新的无效区域,并将那种转变新闻保存在绘图音信结构
       三 、windows不会将八个WM_PAINT消息放到音讯对列
   InvalideateRect函数
      
① 、窗口新闻处理程序能够因此呼叫InvalidateRectangular使展现区域内的矩形无效
      
贰 、调用InvalidateRect函数时一旦音讯队列中早就存在WM_PAINT,即现已存在无效区域,windows将计算新的无效区域。借使音信队列无WM_PAINT则将
          一个WM_PAINT消息投递到新闻队列。
      
叁 、在接到到WM_PAINT音信时,窗口处理程序/函数能够得到无效区域的坐标。
       肆 、在任何时刻能够经过呼叫GetUpdateRect取得无效区域的坐标
   Tip:
      
在处理WM_PAINT音讯时,窗口音讯处理程序在呼叫BeginPaint之后一切区域立时变成有效,
程序也得以透过呼叫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内部保存的数据结构,设备内容与特定的来得设备相关。对于系统桌面,
设备内容总是与显示器上的一定窗口相关
      
三 、设备内容中有些值是图形属性,那一个属性定义了GDI绘图函数的细节。
   通过设备内容绘图的经过:
      
① 、程序须求绘图时,必须得到设备内容句柄,在收获该句柄后,windows系统用钦定的属性值填入其中设备内容结构
       ② 、能够呼叫分歧的GDI函数获取装备内容的属性值
       三 、可以呼叫GDI函数改变设备内容的属性值
       肆 、利用别的GDI函数在体现区域绘图
       ⑤ 、当程序在彰显区域绘图达成后,必须自由设备内容句柄,
被假释的句柄无法再被利用
       六 、程序必须在处理单个新闻处理期间获得和刑满释放解除劳教设备内容句柄。
       Tip:
        
除了呼叫CreateDC建立的装备内容外,程序无法在五个新闻之间保存其余装备内容句柄。
   获取装备内容句柄:  
   方法一:处理WM_PAINT音信时行使
       1、BeginPaint和EndPaint函数
           
BeginPaint和EndPaint函数要求窗口句柄(在windows呼叫应用程序窗口处理函数时,作为参数字传送递给应用程序窗口处理函数)
          和PAINTSTRUCT结构的地方作为参数。
            BeginPaint函数重临2个与窗口相关联的装备内容句柄。
           其原型如下:
                        HDC  BeginPaint(HWND, PAINTSTRUCT *)
          
而EndPaint函数释放由BeginPaint函数取得的装备内容句柄,其原型如下:
                             EndPaint(HWND, PAINTSTURCT *)
       2、WM_PAINT音信处理进度
          PreStep:
                  HDC hdc;
                  PAINTSTRUCT  ps;
          step1:
首先呼叫BeginPaint函数取得四个与窗口相关联的装备内容句柄;
                  hdc=BeginPaint(hwnd,&ps);
          Step2:  使用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;
       肆 、尽管在窗口语资源消息息处理函数中不处理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);//与窗口语资源信息息处理函数基本等同的结构
home88一必发,       5、windows产生WM_PAINT音信是因为显示区域的有些区间变成无效,
假使不呼叫BeginPaint和EndPaint,只怕ValidateRect,则windows
        
不会是无用区域成为有效,相反windows会发送另三个WM_PAINT音讯,且一直发送过去。 
   绘图音信结构  PAINTSTRUCT:
       壹 、绘图音信结构定义:
              typedef struct tagPAINTSTRUCT
                {
                     HDC   hdc;   //设备内容句柄
                     BOOL  fErase;  //是不是曾经擦除无效矩形的背景
                     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(

home88一必发 3

       
叁 、假若程序呼叫InvalidateRect使展现区域中的矩形失效,则InvalidateRect函数的末梢贰个参数会内定是不是擦除背景。假设这么些参数为FALSE
           则windows不会擦除背景,并且在呼唤完BeginPaint后将置
ps.f伊拉斯e=TRUE 非零。
          
在处理WM_PAINT消息时,假诺急需在低效区域外实行重绘,可以呼叫InvalidateRect函数:
            Exp:
                 InvalidateRect(hwnd,NULL,TRUE);
           
在BeginPaint函数在此之前呼叫InvalidateRect函数使全数显示区域成为无效,并擦除背景;但倘使最终3个参数等于FALSE,则不会擦除背景,窗口
            中原始的音讯还保留在原处。
        四 、RECT rcPaint 是三个RECT型的结构体,
PAINTSTRUCT结构中的rcPaint成员定义了不算区域的边界。

下边大家针对CBSColorComboBox类的那些经过来做个大概的牵线:

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

全体2几个矩形具有同样的肥瘦和冲天,那些宽度和高度被保留在cxBlock、cyBlock中。无论哪一天转移客户区的大小,程序都将再一次计算cxBlock、cyBlock。WM_LBUTTONDOWN处理逻辑利用鼠标的坐标来判断哪些矩形被单击,然后在fState数组中选用位运算符(按位异或^)总结那个矩形的新情景,最后强制使该矩形失效,从而发出WM_PAINT消息。

前边的始末简短的叙述了选取BeginPaint和EndPaint函数来处理WM_PAINT新闻的机制,精晓不完了的地点请各位见谅。

  在WM_MEASUREITEM音讯影射函数中设定Item的分寸尺寸的时候,我们只须要设置Item的万丈即可。这里的中度大家设置为2倍的系列小图标(SMALL
ICON)的莫大,其尺寸用::GetSystemMetrics(SM_CXSMICON)取得。

      DWOQashqaiD dwCtrlStyle = 0 , 
//设置内嵌在情景栏上的CStatusBarCtrl对象创立时的扩大风格

假设客户区的上升幅度和惊人不可能被5整除,客户区的左侧或底部就会并发多个小长条区域,不被实行覆盖。在那片区域拓展鼠标单击时,CHECKEKoleos1程序会调用MessageBeep函数举行响应。

    上边的片段函数的原型没有指明重回值类型,
大家能够经过编写翻译环境协调查看, 因为我有点懒,所以就没查看了。

  Visual
C++的先后开发人员能够在Item的矩形区域内画各样各个的音信,例如:图标/位图/字符串等等。那么有人会疑窦:”大家用什么来画?大家在哪里画?又如何来画吗?”。答案其实都在那个LPDRAWITEMSTRUCT结构中。hDC成员为装备上下文环境(HDC),得到了该设备句柄也就象征我们有着了画任何位图/图标/文本的能力;那么接下去的题材就是:大家在何地来画吗?答案也相当粗略:获得LPDRAWITEMSTRUCT结构中Item的矩形区域(rcItem),那么那就是您施展才华的空中了,要丰盛利用它哦!

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

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

    哈哈哈哈…………….原来windows下的程序设计有C的底蕴,加上学习一大堆windows定义各样API函数,
加上部分运维机制的通晓,固然是菜鸟级的不入门的主次编程职员(就如自家一般)也能落实2个总结的应用………………..

  最终一步即是怎么着来画的题材了,说白了正是怎么分配各种成分的上空,如何在它们各自的上空上画出您想要的事物。根据平常一般分别总计出ICON所占的矩形区域/文本所占的矩形区域/位图的矩形区域,假若您还有其余因素那么也应当总计出该因素所占的矩形区域/位图所占的矩形区域。接下来的全体都一点也不细略了,不外乎CDC类的多少个常用函数:画图标用DrawIcon()、画位图用BitBlt()、画文字用DrawText()等函数。要是你觉得视觉上还不够CEOL,你还足以来设置各种Item的公文颜色,背景颜色,以及图标的起来和凹陷的视觉效果。

      UINT nID = AFX_IDW_STATUS_BA君越  
//钦赐状态栏那一个子窗口的ID,暗中同意为AFX_IDW_STATUS_BAR

    小编意识用LiveWrite这一个东西比较好…….

  但是在上述进程中需求专注多少个难点,一是为着消弭不断绘制所推动的闪耀现象,需求在WM_ERASEBKGND新闻响应中作些特殊处理;在WM_PAINT音信中一向把组合框的客户区当成一幅位图来不断更新,而不是对ICON区域和文书区域分别重绘。二是每当用户改变了组合框的脚下内容后,在画新的Item以前一定要记得清除前次组合框内的始末。三是一旦想选用更加多的颜料,那么只要选择组合框中的最终三个Item(More
Colors)即可,这些Item是为用户自定义颜色而专门设置的。

    );

  二 、编制程序步骤

    BOOL Create(

  壹 、运营Visual
C++6.0,生成三个基于对话框的类型,将该类型命名为”WW”;

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

  贰 、使用Class
Wizard新建三个类CBSColorCombo博克斯,其基类选取为CComboBox类;

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

  ③ 、在先后的对话框中放置1个ComboBox控件,使用CLASSWIZA卡宴D添加对应的CComboBox类成员变量,然后将该成员变量的类别修改为CBSColorCombo博克斯;

      UINT nID = AFX_IDW_STATUS_BA途观 
//钦点状态栏这么些子窗口的ID,私下认可为AFX_IDW_STATUS_BAR

  ④ 、添加代码,编写翻译运维程序。

    );

**三 、程序代码

    在先后的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凯雷德L,  //Scroll Lock键的动静提示器

        };

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

          home88一必发 4

      若要修改状态栏的外观,如添加或调整和收缩景况栏上的窗格,只须求在indicators数组中拉长或减弱相应的字符串财富ID即可;

  2.2安装状态栏提醒器(窗格)

    CStatusBar::SetIndicators

  2.3设置提醒器(窗格)的小幅和品格

    CStatusBar::SetPaneInfo

    void SetPaneInfo(

      int nIndex,  //内定要安装其样式的窗格的地点索引

      UINT nID,    //为内定窗格重新安装的新ID

      UINT nStyle,
//窗格的体制:SBPS_NORMAL/SBPS_STRETCH/SBPS_DISABLED/SBPS_POPOUT/SBPS_NOBORDERS

      int cxWidth  //钦赐窗格的小幅度

    );

  2.4安装提醒器(窗格)的文本内容

    CStatusBar::SetPaneText

    BOOL SetPaneText(

      int nIndex, 
//当前窗格在提示器数组(indicators)中的地方索引

      LPCTST汉兰达 lpszNewText,  //要在脚下窗格中显得的文书

      BOOL bUpdate = TRUE

    );

    若不清楚当前窗格在提醒器数组(indicators)中的地方索引,可利用CStatusBar::CommandToIndex

    int CommandToIndex( UINT nIDFind ); 
//依照钦点的财富ID获得对应的地点索引

 

本例将在地方栏上突显当前系统的时间和三个进程条控件:

  壹 、展现系统时间

  在程序能源窗口中的字串表中加进五个新的字符串能源:

  home88一必发 5

  将那多个新的字符串能源ID添加到CMainFrame类的源文件中的indicators数组中:  

static UINT indicators[] =
{
    ID_SEPARATOR,           

    IDS_TIMER,
    IDS_PROGRESS,

    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
};

  利用C提姆e类的静态成员函数GetCurrentTime获取系统当下的日子对象;再调用CTime类的另三个分子函数Format对获取的光阴对象进行格式化,获得二个带有格式化时间的字符串;调用SetPaneInfo函数修改窗格的显得上涨幅度以装下将要显示的字符串文本;调用SetPaneText函数将该字符串展现到状态栏的窗格中;  

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......

    CTime t=CTime::GetCurrentTime();
    CString str=t.Format("%Y-%m-%d %H:%M:%S");
    CClientDC dc(this);
    CSize sz=dc.GetTextExtent(str);
    m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
    m_wndStatusBar.SetPaneText(1,str);
    
    return 0;
}

  此时在状态栏窗格中展现的时刻是一动不动的,利用定时器每隔一秒就发送WM_TIME奇骏音信,在信息响应函数OnTimer中再一次赢得二次系统当下时光并体现到状态栏窗格中,已达到规定的标准凸显动态时间的功用;

  在CMainFrame类的OnCreate函数中埋下定时器: 

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......
    
    SetTimer(1,1000,NULL);
    
    return 0;
}

  为CMainFrame类添加WM_TIMEKuga音讯,生成新闻响应函数OnTimer,在该函数中另行履行2次系统时间的取得并展现到状态栏窗格中: 

void CMainFrame::OnTimer(UINT nIDEvent) 
{
    // TODO: Add your message handler code here and/or call default

    CTime t=CTime::GetCurrentTime();
    CString str=t.Format("%Y-%m-%d %H:%M:%S");
    CClientDC dc(this);
    CSize sz=dc.GetTextExtent(str);
    m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
    m_wndStatusBar.SetPaneText(1,str);
    
    CFrameWnd::OnTimer(nIDEvent);
}

  二 、进程条控件

  要在先后中利用进程栏,首先必要结构一个CProgressCtrl对象,然后调用CProgressCtrl类的Create函数创设进程栏控件;

    BOOL Create(

      DWO奥迪Q7D dwStyle, 
//进程栏控件的门类,窗口全体的项目+PBS_VE大切诺基TICAL(进度栏垂直)/PBS_SMOOTH(进程栏三番五次)

      const RECT& rect,  //进度栏控件的轻重缓急、地点

      CWnd* pParentWnd,  //进程栏的父窗口

      UINT nID   //钦点进程栏控件的ID

    );

  在程序的CMainFrame类中添加成员变量:CProgressCtrl m_progress

    home88一必发 6

  要在状态栏的窗格中呈现进度栏,首先使用GetItemRect函数得到该窗格的区域大小:

    void GetItemRect(int nIndex, LPRECT lpRect ) const;

    nIndex:钦点窗格的任务索引

    lpRect:窗格的矩形区域

  

  当程序窗口第一遍浮现时就会发送WM_PAINT新闻,而且当程序的窗口尺寸发生变化要求重绘时也会发送WM_PAINT消息,故可在WM_PAINT音信的响应函数中判断,若程序还未创造进度栏则创立它,若已开立则将进程栏移动至指标窗格的矩形区域中;

  为CMainFrame类添加WM_PAINT新闻的响应函数:

  home88一必发 7  

void CMainFrame::OnPaint() 
{
    CPaintDC dc(this); // device context for painting
    
    // TODO: Add your message handler code here
    CRect rect;
    m_wndStatusBar.GetItemRect(2,&rect);  //获得状态栏中窗格的矩形区域
    if(!m_progress.m_hWnd){   //判断当m_progress对象的句柄为NULL时,说明该对象还未创建,则创建进度栏
        m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123);  //创建进度栏
    }else{
        m_progress.MoveWindow(rect);  //将进度栏移至目标矩形中
    }
    
    m_progress.SetPos(50);  //设置进度栏的当前进度
    
    // Do not call CFrameWnd::OnPaint() for painting messages
}

  若要达成速度栏进程的动态扩大,须求选择定时器,在WM_TIME大切诺基音信的响应函数OnTimer函数中贯彻:  

void CMainFrame::OnTimer(UINT nIDEvent) 
{
    ......

    m_progress.StepIt();
    
    CFrameWnd::OnTimer(nIDEvent);
}

    CProgressCtrl::StepIt:使进程栏控件的快慢根据一定的增长幅度扩充

    CProgressCtrl::SetStep:设置进程栏每一回扩展的大幅度

    CProgressCtrl::SetRange:设置进度栏的限量,暗许为0~100

  ③ 、在气象栏上显示鼠标当前的职位

    当在先后的客户区窗口移动鼠标时,将鼠标当前的坐标地方呈现在状态栏的提醒行上;

    首先必要在先后的CStyleView类中添加WM_MOUSEMOVE音信的响应函数:

      home88一必发 8

    因为GetParent函数重返的为CWnd类型的指针,要求强制转换为CMainFrame类型的指针,故须在视图类的源文件中含有框架类的头文件:

      #include “MainFrm.h”

    在WM_MOUSEMOVE音信的响应函数中,完结状态栏对象的收获及在其窗格中的文本显示:      

void CStyleView::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CString str;
    str.Format("x=%d,y=%d",point.x,point.y);  //格式化鼠标坐标位置的信息
    //通过调用GetParent函数获取视图类的父窗口即框架类窗口,将返回值强制转换后,调用框架窗口对象中的状态栏成员变量
    ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
    
    CView::OnMouseMove(nFlags, point);
}

    将鼠标当前岗位消息展现到状态栏对象的提醒行中的方法:

      方法一:SetWindowText

        框架类CMainFrame类的景观栏成员变量m_wndStatusBar默许在CMainFrame类的头文件中被定义为protected类型,须手动将其修改为public类型才能被调用;

      方法二:CFrameWnd类的积极分子函数:SetMessageText

        该函数的机能即为在ID为0的场地栏窗格(即指示行)设置二个字符串;因先后框架类CMainFrame类派生于CFrameWnd类,故那里能够一向用框架类对象调用该成员函数来安装境况栏文本;        

void CStyleView::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CString str;
    str.Format("x=%d,y=%d",point.x,point.y);
    //((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
    ((CMainFrame*)GetParent())->SetMessageText(str);
    
    CView::OnMouseMove(nFlags, point);
}

      方法三:CFrameWnd类的分子函数:GetMessageBar

        该函数重回状态栏对象的指针,故无须像方法一那样修改并调用CMainFrame类的保卫安全成员变量m_wndStatusBar了,可直接调用SetWindowText函数设置状态栏的首先个窗格(提示行)的公文;       

void CStyleView::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CString str;
    str.Format("x=%d,y=%d",point.x,point.y);
    //((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
    //((CMainFrame*)GetParent())->SetMessageText(str);
    ((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
    
    CView::OnMouseMove(nFlags, point);
}

      方法四:CWnd类的分子函数:GetDescendantWindow

        该函数可透过点名的ID来获取当前窗口的具有子孙窗口,因情形栏属于框架类窗口,故先要获得框架类窗口的指针,然后根据状态栏的窗口ID调用该函数到手状态栏对象的指针       

void CStyleView::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CString str;
    str.Format("x=%d,y=%d",point.x,point.y);
    //((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
    //((CMainFrame*)GetParent())->SetMessageText(str);
    //((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
    GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);
    
    CView::OnMouseMove(nFlags, point);
}

 

发表评论

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

网站地图xml地图