扩展颜色对话框 - (关键字:CHOOSECOLOR,CColorDialog,通用对话框)

类别:VC语言 点击:0 评论:0 推荐:

原创,转载请注明出处。
--------------------------------------------------
样品:

材料:
(1) 参数
typedef struct {
  DWORD        lStructSize;
  HWND         hwndOwner;
  HWND         hInstance;
  COLORREF     rgbResult;
  COLORREF   * lpCustColors;
  DWORD        Flags;
  LPARAM       lCustData;
  LPCCHOOKPROC lpfnHook;
  LPCTSTR      lpTemplateName;
} CHOOSECOLOR, *LPCHOOSECOLOR;

(2) API函数
BOOL ChooseColor(
  LPCHOOSECOLOR lpcc   // initialization data
);

(3) 回调函数,用于处理消息
UINT_PTR CALLBACK CCHookProc(
  HWND hdlg,      // handle to dialog box
  UINT uiMsg,     // message identifier
  WPARAM wParam,  // message parameter
  LPARAM lParam   // message parameter
);

方法:
(1)、填写结构体:
 COLORREF retColor = RGB( 255,0,0);
 COLORREF cusColor[16];
 memset( cusColor, 0, sizeof( COLORREF) * 16 );

 CHOOSECOLOR cc = {
   sizeof( CHOOSECOLOR ),
   m_hwndParent, // 父窗口啦,设置为NULL的话,就是桌面了
   NULL,  // 一个句柄,没用到,详看MSDN
   retColor,  // 如果设置了CC_RGBINIT 就是初始的颜色值了,同时它作为返回值,返回所选择的颜色
   cusColor, // 初始的自定义颜色数组,设置为NULL的话,会出错,不设置的话,好像就是随机值了,我把它都清理成0了
   CC_RGBINIT|CC_FULLOPEN | CC_ENABLEHOOK | CC_ANYCOLOR, // 红色为设置自己的消息处理函数
     NULL,
   (LPCCHOOKPROC)MyCCHookProc, // 使用自定义的消息处理函数
   NULL
   };
(2)、调用
    ChooseColor( &cc ); // 点击"确定"返回 TRUE, 否则返回 FALSE
(3)、自定义的消息处理函数
HWND hAlpha;// 用于显示alpha值的文本框
int xCurrentScroll;// 用于保存滚动条的当前值,同时也是alpha值
UINT_PTR CALLBACK CAColorDialog::MyCCHookProc(
   HWND hdlg,      // handle to dialog box
   UINT uiMsg,     // message identifier
   WPARAM wParam,  // message parameter
   LPARAM lParam   // message parameter
   )
{
 HWND hctrl;
 RECT rt;
 POINT pt;
 
 int Delta;     // xDelta = new_pos - current_pos 
 int xNewPos;    // new position
 BOOL fScroll = FALSE;
 
 switch( uiMsg )
 {
 case WM_INITDIALOG:

  ASSERT( pthis );
  // 修改颜色对话框的大小
  ::GetWindowRect( hdlg, &rt );
  rt.bottom += 20;
  ::SetWindowPos( hdlg, NULL, 0,0, rt.right - rt.left,
      rt.bottom - rt.top , SWP_NOMOVE );
  // 修改“取消”按钮的位置
  hctrl = ::GetDlgItem( hdlg, IDCANCEL );
  ::GetWindowRect( hctrl, &rt );
  pt.x = rt.left;
  pt.y = rt.top ;
  ::ScreenToClient( hdlg, &pt );
  pt.x += 250;
  pt.y += 22;
  ::SetWindowPos( hctrl, NULL, pt.x, pt.y , 0, 0, SWP_NOSIZE );
  // 修改“确定”按钮的位置
  hctrl = ::GetDlgItem( hdlg, IDOK );
  ::GetWindowRect( hctrl, &rt );
  pt.x = rt.left;
  pt.y = rt.top ;
  ::ScreenToClient( hdlg, &pt );
  pt.x += 250;
  pt.y += 22;
  ::SetWindowPos( hctrl, NULL, pt.x, pt.y , 0, 0, SWP_NOSIZE );
  // 添加滚动条
  pt.x -= 250;
  hctrl = CreateWindowEx(
      0L,
      "ScrollBar",
      "alpha channel",
      SBS_TOPALIGN|SBS_LEFTALIGN|WS_CHILD |WS_VISIBLE | WS_TABSTOP,
      pt.x,
      pt.y,
      160,
      20,
      hdlg,
      NULL,
      NULL,
      NULL );
  ::SetScrollRange( hctrl, SB_CTL, 0, 255, TRUE );
  ::SetScrollPos( hctrl, SB_CTL, 128, FALSE );
  xCurrentScroll = 128;
  
  // 添加一个文本框,用于显示当前透明度
  pt.x += 162;
  hAlpha = CreateWindowEx(
    0L,
    "Edit",
    "alpha value",
    //ES_READONLY|
    ES_LEFT|ES_NUMBER|WS_CHILD |WS_VISIBLE | WS_TABSTOP,
    pt.x,
    pt.y,
    36,
    20,
    hdlg,
    NULL,
    NULL,
    NULL );
  pt.x -= 162;
  // 添加一个静态文本,字体有点问题
  pt.y -= 22;
  hctrl = CreateWindowEx(
    0L,
    "STATIC",
    "透明度(255表示完全不透明)",
    WS_CHILD |WS_VISIBLE ,
    pt.x,
    pt.y,
    220,
    20,
    hdlg,
    NULL,
    NULL,
    NULL );

  ::SetWindowText( pthis->hAlpha, "128" );
  break;
 case WM_HSCROLL:
  {
   hctrl = (HWND)lParam;
   // 滚动条的事件处理,摘自MSDN
   switch (LOWORD(wParam))
   {
    // 键盘上的pageup/down
    case SB_PAGEUP:
     xNewPos = xCurrentScroll - 20;
     break;
    case SB_PAGEDOWN:
     xNewPos = xCurrentScroll + 20;
     break;
    // 单击左右箭头,或者用键盘上的方向键
    case SB_LINEUP:
     xNewPos = xCurrentScroll - 1;
     break;
    case SB_LINEDOWN:
     xNewPos = xCurrentScroll + 1;
     break;
    // 用鼠标拖动滑杆(结束)
    case SB_THUMBPOSITION:
     xNewPos = HIWORD(wParam);
     break;
    // 用鼠标拖动滑杆(过程)
    case SB_THUMBTRACK:
     xNewPos = HIWORD(wParam);
     break;
    default:
     xNewPos = xCurrentScroll;
   }
 
   xNewPos = max(0, xNewPos);
   xNewPos = min(255, xNewPos);
   if (xNewPos == xCurrentScroll)
    break;
   fScroll = TRUE;
   Delta = xNewPos - xCurrentScroll; 
   xCurrentScroll = xNewPos;
 
   // Reset the scroll bar.
   SetScrollPos( hctrl, SB_CTL, xCurrentScroll, fScroll );
   char str[4];
   strset(str, 0);
   sprintf( str, "%d", xCurrentScroll );
   ::SetWindowText( hAlpha, str );
   break;
  }
/*
 case WM_COMMAND:
  if( LOWORD(wParam) == IDOK ) // 确定按钮
  {
//   TRACE("IDOK click");
   char str[];
   ::GetWindowText(hAlpha, str, 3 );
   atoi( str );
  }
*/
 }
 // 返回 0 ,表示由默认的消息处理函数继续进行处理
 // 返回非0的话,会很郁闷
 return 0;
}
// -----------------------------------------------------------
这样就好了
使用CColorDialog的话,可以用子类化的方法,CodeProject上有个例子
http://www.codeproject.com/dialog/select_all_button.asp
// -----------------------------------------------------------
另外,曾试着封装成一个类,遇到了一些难题:
1、如何把回调函数作为类的方法?
      方法:设置成静态成员,static
2、如何让静态成员访问类里的数据?
      方法:在类里添加一个静态类指针,eg:
--- .h file ---
class MyColorDialog:
{
    MyColorDialog()
    {
        pthis = this;
    }
    static MyColorDialog* pthis;
    static UINT CALLBACK MyCCHookProc( ... );
}
--- .cpp file ---
MyColorDialog* MyColorDialog::pthis = NULL; // 重要,不然会出链接错误
...


本文地址:http://com.8s8s.com/it/it661.htm