DRAWITEMSTRUCT

来源:互联网 发布:ky网络用语是什么意思 编辑:程序博客网 时间:2024/05/14 06:41
 

DRAWITEMSTRUCT 为需要自绘的控件或者菜单项提供了必要的信息。
在需要绘制的控件或者菜单项对应的WM_DRAWITEM消息函数中得到一个指向该结构的指针。   
例子:   
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) (.cpp中定义)   

这里LPDRAWITEMSTRUCT即指向DRAWITEMSTRUCT结构体的指针。   

DRAWITEMSTRUCT结构的定义如下:   
typedef struct tagDRAWITEMSTRUCT
{   
UINT CtlType;   
UINT CtlID;   
UINT itemID;   
UINT itemAction;   
UINT itemState;   
HWND hwndItem;   
HDC hDC;   
RECT rcItem;   
ULONG_PTR itemData;   
} DRAWITEMSTRUCT, NEAR *PDRAWITEMSTRUCT, FAR *LPDRAWITEMSTRUCT;
结构成员:   
成员:   
CtlType   指定了控件的类型,其取值如下表所示。   
ODT_BUTTON:按钮控件   
ODT_COMBOBOX:组合框控件   
ODT_LISTBOX:列表框控件   
ODT_LISTVIEW:列表视图控件   
ODT_MENU:菜单项   
ODT_STATIC:静态文本控件   
ODT_TAB:Tab控件   
CtlID   指定了自绘控件的ID值,而对于菜单项则不需要使用该成员   
itemID   表示菜单项ID,也可以表示列表框或者组合框中某项的索引值。
          对于一个空的列表框或组合框,该成员的值为–1。
这时应用程序只绘制焦点矩形(该矩形的坐标由rcItem 成员给出)虽然此时控件中没有需要显示的项,
但是绘制焦点矩形还是很有必要的,因为这样做能够提示用户该控件是否具有输入焦点。
当然也可以设置itemAction 成员为合适值,使得无需绘制焦点。   

itemAction   指定绘制行为,其取值可以为下表中所示值的一个或者多个的联合。   
         ODA_DRAWENTIRE:当整个控件都需要被绘制时,设置该值   
         ODA_FOCUS:如果控件需要在获得或失去焦点时被绘制,则设置该值。此时应该检查itemState成员,
                    以确定控件是否具有输入焦点。   
         ODA_SELECT   如果控件需要在选中状态改变时被绘制,则设置该值。
                        此时应该检查itemState 成员,以确定控件是否处于选中状态。   
itemState   指定了当前绘制操作完成后,所绘项的可见状态。例如,如果菜单项应该被灰色显示,
              则可以指定ODS_GRAYED状态标志。其取值可以为下表中所示值的一个或者多个的联合。   
         ODS_CHECKED:如果菜单项将被选中,则可设置该值。该值只对菜单项有用。   
         ODS_COMBOBOXEDIT:在自绘组合框控件中只绘制选择区域。   
         ODS_DEFAULT:默认值。   
         ODS_DISABLED:如果控件将被禁止,则设置该值。   
         ODS_FOCUS:如果控件需要输入焦点,则设置该值。   
         ODS_GRAYED:如果控件需要被灰色显示,则设置该值。该值只在绘制菜单时使用。   
         ODS_HOTLIGHT:Windows 98/Me, Windows 2000/XP: 如果鼠标指针位于控件之上,则设置该值,
                      这时控件会显示高亮颜色。   
         ODS_INACTIVE:Windows 98/Me, Windows 2000/XP: 表示没有激活的菜单项。
       ODS_NOACCEL:Windows 2000/XP: 控件是否有快速键盘。   
         ODS_NOFOCUSRECT:Windows 2000/XP: 不绘制捕获焦点的效果。   
         ODS_SELECTED:选中的菜单项。   
hwndItem   指定了组合框、列表框和按钮等自绘控件的窗口句柄;
             如果自绘的对象时菜单项,则表示包含该菜单项的菜单句柄。   
hDC   指定了绘制操作所使用的设备环境。   
rcItem   指定了将被绘制的矩形区域。这个矩形区域就是上面hDC的作用范围。
          系统会自动裁剪组合框、列表框或按钮等控件的自绘制区域以外的部分。
         也就是说rcItem中的坐标点(0,0)指的就是控件的左上角。但是系统不裁剪菜单项,
         所以在绘制菜单项的时候,必须先通过一定的换算得到该菜单项的位置,
           以保证绘制操作在我们希望的区域中进行。   
itemData   对于菜单项,该成员的取值可以是由   
CMenu::AppendMenu、   CMenu::InsertMenu或者   CMenu::ModifyMenu   等函数传递给菜单的值。
   对于列表框或这组合框,该成员的值可以为由   ComboBox::AddString、  
       CComboBox::InsertString、   CListBox::AddString或者   CListBox::InsertString
   等传递给控件的值。   如果ctlType 的取值是ODT_BUTTON或者ODT_STATIC, itemData的取值为0。

 


FillRect  
函数功能:该函数用指定的画刷填充矩形,此函数包括矩形的左上边界,但不包括矩形的右下边界。

函数原型:
int FillRect(HDC hdc, CONST RECT *lprc, HBRUSH hbr);
{
( void FillRect( LPCRECT lpRect, CBrush* pBrush );
}   

参数:   
hdc:设备环境句柄。   
lprc:指向含有将填充矩形的逻辑坐标的RECT结构的指针。   
hbr:用来填充矩形的画刷的句柄。   

返回值:
如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

备注:由参数hbr定义的画刷可以是一个逻辑现刷句柄也可以是一个颜色值,
      如果指定一个逻辑画刷的句柄,调用下列函数之一来获得句柄;
      CreateHatchBrush、CreatePatternBrush或CreateSolidBrush。
 
此外,你可以用GetStockObject来获得一个库存画刷句柄。如果指定一个颜色值,
必须是标准系统颜色(所选择的颜色必须加1)

如FillRect(hdc, &rect, (HBRUSH)(COLOR_ENDCOLORS+1)),
参见GetSysColor可得到所有标准系统颜色列表。   

当填充一个指定矩形时,FillRect不包括矩形的右、下边界。无论当前映射模式如何,
GDI填充一个矩形都不包括右边的列和下面的行。  


FillRect在VC++里面的使用

//得到客户区域设备环境变量   
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
GetClientRect(&m_ClientRect); //得到客户区域矩形   
if(m_Btntype == 0) //判断当前按钮类型是否为高级彩色按钮
  {   
       switch(m_State)
     {   
         case 0:   
         pDC->FillRect(&m_ClientRect,new CBrush(RGB(255,255,255)));
         break;   
         case 1:   
         pDC->FillRect(&m_ClientRect,new CBrush(RGB(192,192,255)));
  }

 

FrameRect  
函数功能:该函数用指定的画刷为指定的矩形画边框。边框的宽和高总是一个逻辑单元。

函数原型:
int FrameRect(HDC hdc, CONST RECT *lprc, HBRUSH hbr);
参数:

hdc:将要画边框的设备环境句柄。   
lprc:指向包含矩形左上角和右下角逻辑坐标的结构RECT的指针。
      也可以传递一个CRECT对象给这个参数。   
hbr:用于画边框的画刷句柄。   
返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

备注:由参数hbr定义的画刷必须是由CreateHatchBrush、CreatePatternBrush或
      CreateSolidBrush创建的,或者是由使用GetStockObject获得的。   
如果RECT结构中的底部成员的值少于或等于顶部成员,或右部成员少于或等于左部成员,
此函数画不了矩形。  

 

 


Polygon
含义
1、polygon:名词,指 多边形、多角形   
2、指多边形函数   
3、用多变形函数画一个由直线组成的、有两个以上顶点的多边形,并用当前画笔画多边形轮廓,
   用当前画刷和多边形填充模式填充。   
4、GIS中的基本图形,参考point、line等


函数功能

该函数画一个由直线相连的两个以上顶点组成的多边形,用当前画笔画多边形轮廓,
用当前画刷和多边形填充模式填充多边形。

函数原型
  BOOL Polygon(HDC hdc, CONST POINT *lpPoints, int nCount);
函数参数
 
  hdc:设备环境句柄。   
   lpPoints:指向用于指定多边形顶点的POINT结构数组的指针。
             lpPoints中坐标以当前位置为原点。   
   nCount:指定数组中顶点个数,此值必须大于等于2。   

返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。   

备注:此多边形通过画一条从最后一个顶点到第一个顶点的线段而自动闭合起来。
函数Polygon不使用和改变   当前位置。   

 

 

FillRect API
顧名思義,FillRect 是在一塊矩形區域填入顏色:

int FillRect(
  HDC    hDC,           // handle to device context
  CONST  RECT *lprc,    // pointer to structure with rectangle
  HBRUSH hbr            // handle to brush
);
hDC 是指設備內容代碼,您或許覺得奇怪,此處既沒有呼叫 BeginPaint,也沒有 GetDC,那麼那來的 hDC 呢?
還記得之前提到 WM_DRAWITEM 的 lParam 參數中便包含了設備內容代碼。或許您可以想像:
當 Windows 要畫出一般的選項時,其內部必定也有一設備內容供系統繪製之用,
但是遇到具有 MFT_OWNERDRAW 類型的選項時,卻是交由程式的視窗函式自行繪製,
因此藉由 WM_DRAWITEM 的 DRAWITEMSTRUCT 結構體將繪製所需資料傳給視窗函式,
其內便包含了設備內容代碼及設備內容的範圍。

lprc 是指向一個描述矩形的結構體,其欄位參考第三章。
hbr 是畫刷代碼,此畫刷將被用來填入前述矩形範圍內,這個畫刷也就是我們在 WM_CREATE
 所建立的 hbrMenuBkHiligh 與 mi.hbrBack,至於要使用那一種,由滑鼠是否移到該選項上決定,
這個可以由 DRAWITEMSTRUCT 中的 itemState 欄位決定,若該欄位的 ODS_SELECTED 被設定
 ( 為 1 時 ) 表示滑鼠移到該選項上面,此時需用 hbrMenuBkHiligh,反之則用 mi.hbrBack。

在描繪檔案子選單裏的選項時,先取得選項識別碼,選項識別碼減去 100h 即為選項位置,
再乘以四即得選項在 lpszFile、hbmpFile、dwFileWidth、dwFileHeight、ybmPosition 各陣列位址,
接下來就是把選項文字位址推入堆疊,接著呼叫 SelectObject 選擇位元圖代碼
 ( 此代碼由 hbmpFile 獲得 ),接著就是呼叫 BitBlt 把記憶體設備內容拷貝到選項設備內容裏,
其位元圖大小由 dwFileWidth、dwFileHeight 兩陣列取得,而要拷貝到選項設備內容的何處則由
 ybmPosition 陣列取得。接著設定文字要畫在何處,小木偶設為在位元圖之後六點的地方,由程式


        add     dis.rcItem.left,6
        add     dis.rcItem.left,eax
達成。緊接著是設定文字顏色與文字背景色,
分別呼叫 SetTextColor 與 SetBkColor 兩個 Win32 API。程式如下:

        test    dis.itemState,ODS_SELECTED
        jz      n_sel0
        mov     ecx,dwSelTextColor
        push    dwSelBkColor
        jmp     @f
n_sel0: mov     ecx,dwTextColor
        push    dwSelTextColor          ;沒被選擇的背景色即為被選到的文字顏色
@@:     invoke  SetTextColor,dis.hdc,ecx
        push    dis.hdc
        call    SetBkColor
最後一行小木偶並非用

        invoke  SetBkColor,dis.hdc,背景顏色
這是因為在呼叫 SetTextColor 之前背景色就已經被推入堆疊了 ( 因為滑鼠游標是否在選項上,所顯示背景色不同,因此推入不同之顏色,見紅色的那兩行 )。還記得,invoke 是一個假指令,可以分成許多 push 指令及一個 call 指令嗎?若不記得的話,請參考第一章。小木偶這樣寫是為了節省幾個位元組,當然這樣會造成維護不易,這是組合語言的特點,不僅在 DOS 等 16 位元的 Assembly 如此,在 Win32 Assembly 也會有這樣的特色。如果不這樣寫的話,也可以像下面這樣:

        test    dis.itemState,ODS_SELECTED
        jz      n_sel0
        mov     ecx,dwSelTextColor
        mov     edx,dwSelBkColor
        jmp     @f
n_sel0: mov     ecx,dwTextColor
        mov     edx,dwSelTextColor
@@:     push    edx
        invoke  SetTextColor,dis.hdc,ecx
        pop     edx
        invoke  SetBkColor,dis.hdc,edx
不過佔用位元組較多,速度稍慢 ( 可能慢個幾奈秒吧?)。

在描繪字形子選單時,先取得選項文字位址,同樣也推入堆疊,再依此位址之字形建立邏輯字形,用 SelectObject 選擇此新建立的邏輯字形。接著依據滑鼠游標是否在選項上分成兩種情形。第一種是滑鼠游標在選項上,此時只需設定文字及文字背景色即可。第二種情形是滑鼠游標不在選項上時,此時除了必須設定文字外,並不需要設定文字背景顏色,這是因為我們想把文字的背景設為透明的,這樣才能較完整的表現出背景位元圖上的美女,所以此處牽涉了兩個工作:用 BitBlt 畫出位元圖,用 SetBkMode 設定透明的背景顏色。接著不管滑鼠游標是否在選項上,都必需設定文字顏色。最後再畫出文字即可。底下是這段程式所用到的 Win32 API。