本文介绍LisBox的自绘模式的实现.Listbox分为单列模式和多列模式.ListBox,Button等的自绘模式都是通过重载WM_DRAWITEM消息实现.以下代码为MiniWin-GUI系统的实现,WIN32通用
本文实现为单列模式,多列模式的实现只需要在创建ListBox控件的时候指定LBS_MULTICOLUMN样式.并通过LB_SETCOLUMNWIDTH消息设置没列的宽度,就可,对于单列模式如果指定LBS_OWNERDRAWVARIABLE样式可以为每一个列表项设置不同的高度.但是多列模式每个列表项的宽度高度是相同的.多列模式只能用LBS_OWNERDRAWFIXED样式.
以下为效果图和参考代码.
/**/
//
// mainMenu.c: implementation of the mainMenu class.
//
/**/ //
#include " dvbutils.h "
#include " imagelist.h "
#define IDT_MAINMENU_TIMER 100
#define IDC_MAINMENU_TITLE 101
#define IDC_MAINMENU_MENU 104
#define IDC_VIDEO 105
static void DoAction( int idx)
... {
switch(idx)
...{
case 0:CreateEpgWnd(GROUP_VIDEO);break;//CreateDtvPgmWnd();break;
case 1:CreateEpgWnd(GROUP_AUDIO);break;
case 2:CreateNvodWnd();break;
//CreateChnlListWnd();break;
//CreatePFWnd();break;
case 3:break;
case 4:CreateMailWnd();break;
case 5:SearchChannelWnd();break;
case 6:CreateSysSetWindow();break;
default:break;
}
}
static LRESULT WINAPI MenuWndProc(HWND hwnd,UINT msgID,WPARAM wParam,LPARAM lParam)
... {
switch(msgID)
...{
case WM_COMMAND:
switch(wParam)
...{
case MAKELONG(IDC_MAINMENU_MENU,LBN_DBLCLK):
DoAction(SendMessage((HWND)lParam,LB_GETCURSEL,0,0));
break;
}
break;
case WM_DRAWITEM:
...{
DRAWITEMSTRUCT*ds=(DRAWITEMSTRUCT*)lParam;
HDC hdc=(HDC)ds->hDC;
RECT rc=ds->rcItem;
char text[128];
//画菜单选项
if(wParam==IDC_MAINMENU_MENU)
...{
HBITMAP hobmp,hbmp;
HDC hmdc=CreateCompatibleDC((HDC)hdc);
RECT rc=ds->rcItem;
if(ds->itemState&(ODS_SELECTED|ODS_FOCUS))...{
hbmp=(HBITMAP)LoadImage(hInstDVBRes,MAKEINTRESOURCE(IDB_FOCUS),IMAGE_BITMAP,0,0,0);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbmp);
BitBlt((HDC)hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hmdc,0,0,SRCCOPY);
SetTextColor(hdc,RGB(255,255,255));
}else...{
hbmp=(HBITMAP)LoadImage(hInstDVBRes,MAKEINTRESOURCE(IDB_NORMAL),IMAGE_BITMAP,0,0,0);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbmp);
BitBlt((HDC)hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hmdc,0,0,SRCCOPY);
SetTextColor(hdc,RGB(0,0,0));
}
hbmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hobmp);
DeleteObject((HGDIOBJ)hbmp);
DeleteDC(hmdc);
//写菜单项文字
rc.left+=50;
SetBkMode(hdc,TRANSPARENT);
SendMessage(ds->hwndItem,LB_GETTEXT,ds->itemID,(LPARAM)text);
DrawText(hdc,text,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
//写菜单项数字
rc.left+=197;
SetBkMode(hdc,TRANSPARENT);
sprintf(text,"%d",ds->itemID+1);
DrawText(hdc,text,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
}
return 0;
}
case WM_MEASUREITEM:
...{
MEASUREITEMSTRUCT *ms=(MEASUREITEMSTRUCT*)lParam;
ms->itemHeight=47;
return 0;
}
case WM_VKEYTOITEM:
...{
UINT vkey = LOWORD(wParam); // virtual-key code
UINT nCaretPos = HIWORD(wParam); // caret position
if(vkey!=VK_RETURN)
return -1;
DoAction(nCaretPos);
}
return -1;
case WM_ERASEBKGND:
...{
HBRUSH hbBorder;
HDC hmdc=CreateCompatibleDC((HDC)wParam);
//画背景
hbBorder=CreateSolidBrush(RGB(61,185,197));
FillRect((HDC)wParam,NULL,hbBorder);
DeleteObject((HGDIOBJ)hbBorder);
//画标题背景
...{
RECT rc;
HBITMAP hobmp,hbmpTitle;
HBRUSH hbrush;
BITMAP bmp;
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINTITLE));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.bottom=rc.top+bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINHELP));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.top=rc.bottom-bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
}
DeleteDC(hmdc);
}
return 1;
case WM_ACTIVATE:
return DefWindowProc(hwnd,msgID,wParam,lParam);
default:
return DefWindowProc(hwnd,msgID,wParam,lParam);
}
return 0;
}
HWND CreateMainMenu( void )
... {
HWND menuWnd,menu,helpwin;
menuWnd=CreateMainWindow(NULL,WS_TABSTOP|WS_OVERLAPPED,40,30,650,516,MenuWndProc);
//标题
CreateWindow("Static","主 菜 单",WS_VISIBLE|WS_CHILD,//|SS_OWNERDRAW,
50,10,192,22,menuWnd,(HMENU)IDC_MAINMENU_TITLE,NULL,NULL);
//视频播放窗口
CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_OWNERDRAW,30,200,260,200,
menuWnd,(HMENU)IDC_VIDEO,NULL,NULL);
menu=CreateWindow("Listbox",NULL,WS_TABSTOP|WS_VISIBLE|WS_CHILD|LBS_NOTIFY|
LBS_WRAP|LBS_HASSTRINGS|LBS_OWNERDRAWFIXED|LBS_WANTKEYBOARDINPUT,
340,125,310,42*7,menuWnd,(HMENU)IDC_MAINMENU_MENU,NULL,NULL);
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"数字电视");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"广播节目");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"视频点播");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"游戏");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"短信");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"频道搜索");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"系统设置");
SendMessage(menu,LB_SETITEMHEIGHT,0,42);
SendMessage(menu,LB_SETCURSEL,0,0);
...{
TBBUTTON toolbarBtns[] = ...{
...{0, 0, 0, BTNS_SEP, ...{0, 0}, 0, 0},
...{0, 123, TBSTATE_ENABLED,BTNS_BUTTON, ...{0, 0}, 0, "选择"},
...{1, 122, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0,"[确认]进入下级菜单"},
...{2, 133, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, "Test"},
...{3, 144, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
};
HWND htoolbar=CreateToolbarEx(menuWnd, WS_CHILD|WS_VISIBLE|
TBSTYLE_LIST|TBSTYLE_TRANSPARENT|TBSTYLE_FLAT|CCS_BOTTOM,
1234, 2, hInstDVBRes, IDB_ARROWKEYS, toolbarBtns,
sizeof(toolbarBtns)/sizeof(TBBUTTON),32, 16, 32, 16, sizeof(TBBUTTON));
SendMessage(htoolbar,TB_SETEXTENDEDSTYLE,0, TBSTYLE_EX_DRAWDDARROWS);
}
ShowWindow(menuWnd,SW_SHOW);
return menuWnd;
}
// mainMenu.c: implementation of the mainMenu class.
//
/**/ //
#include " dvbutils.h "
#include " imagelist.h "
#define IDT_MAINMENU_TIMER 100
#define IDC_MAINMENU_TITLE 101
#define IDC_MAINMENU_MENU 104
#define IDC_VIDEO 105
static void DoAction( int idx)
... {
switch(idx)
...{
case 0:CreateEpgWnd(GROUP_VIDEO);break;//CreateDtvPgmWnd();break;
case 1:CreateEpgWnd(GROUP_AUDIO);break;
case 2:CreateNvodWnd();break;
//CreateChnlListWnd();break;
//CreatePFWnd();break;
case 3:break;
case 4:CreateMailWnd();break;
case 5:SearchChannelWnd();break;
case 6:CreateSysSetWindow();break;
default:break;
}
}
static LRESULT WINAPI MenuWndProc(HWND hwnd,UINT msgID,WPARAM wParam,LPARAM lParam)
... {
switch(msgID)
...{
case WM_COMMAND:
switch(wParam)
...{
case MAKELONG(IDC_MAINMENU_MENU,LBN_DBLCLK):
DoAction(SendMessage((HWND)lParam,LB_GETCURSEL,0,0));
break;
}
break;
case WM_DRAWITEM:
...{
DRAWITEMSTRUCT*ds=(DRAWITEMSTRUCT*)lParam;
HDC hdc=(HDC)ds->hDC;
RECT rc=ds->rcItem;
char text[128];
//画菜单选项
if(wParam==IDC_MAINMENU_MENU)
...{
HBITMAP hobmp,hbmp;
HDC hmdc=CreateCompatibleDC((HDC)hdc);
RECT rc=ds->rcItem;
if(ds->itemState&(ODS_SELECTED|ODS_FOCUS))...{
hbmp=(HBITMAP)LoadImage(hInstDVBRes,MAKEINTRESOURCE(IDB_FOCUS),IMAGE_BITMAP,0,0,0);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbmp);
BitBlt((HDC)hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hmdc,0,0,SRCCOPY);
SetTextColor(hdc,RGB(255,255,255));
}else...{
hbmp=(HBITMAP)LoadImage(hInstDVBRes,MAKEINTRESOURCE(IDB_NORMAL),IMAGE_BITMAP,0,0,0);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbmp);
BitBlt((HDC)hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hmdc,0,0,SRCCOPY);
SetTextColor(hdc,RGB(0,0,0));
}
hbmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hobmp);
DeleteObject((HGDIOBJ)hbmp);
DeleteDC(hmdc);
//写菜单项文字
rc.left+=50;
SetBkMode(hdc,TRANSPARENT);
SendMessage(ds->hwndItem,LB_GETTEXT,ds->itemID,(LPARAM)text);
DrawText(hdc,text,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
//写菜单项数字
rc.left+=197;
SetBkMode(hdc,TRANSPARENT);
sprintf(text,"%d",ds->itemID+1);
DrawText(hdc,text,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
}
return 0;
}
case WM_MEASUREITEM:
...{
MEASUREITEMSTRUCT *ms=(MEASUREITEMSTRUCT*)lParam;
ms->itemHeight=47;
return 0;
}
case WM_VKEYTOITEM:
...{
UINT vkey = LOWORD(wParam); // virtual-key code
UINT nCaretPos = HIWORD(wParam); // caret position
if(vkey!=VK_RETURN)
return -1;
DoAction(nCaretPos);
}
return -1;
case WM_ERASEBKGND:
...{
HBRUSH hbBorder;
HDC hmdc=CreateCompatibleDC((HDC)wParam);
//画背景
hbBorder=CreateSolidBrush(RGB(61,185,197));
FillRect((HDC)wParam,NULL,hbBorder);
DeleteObject((HGDIOBJ)hbBorder);
//画标题背景
...{
RECT rc;
HBITMAP hobmp,hbmpTitle;
HBRUSH hbrush;
BITMAP bmp;
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINTITLE));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.bottom=rc.top+bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINHELP));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.top=rc.bottom-bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
}
DeleteDC(hmdc);
}
return 1;
case WM_ACTIVATE:
return DefWindowProc(hwnd,msgID,wParam,lParam);
default:
return DefWindowProc(hwnd,msgID,wParam,lParam);
}
return 0;
}
HWND CreateMainMenu( void )
... {
HWND menuWnd,menu,helpwin;
menuWnd=CreateMainWindow(NULL,WS_TABSTOP|WS_OVERLAPPED,40,30,650,516,MenuWndProc);
//标题
CreateWindow("Static","主 菜 单",WS_VISIBLE|WS_CHILD,//|SS_OWNERDRAW,
50,10,192,22,menuWnd,(HMENU)IDC_MAINMENU_TITLE,NULL,NULL);
//视频播放窗口
CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_OWNERDRAW,30,200,260,200,
menuWnd,(HMENU)IDC_VIDEO,NULL,NULL);
menu=CreateWindow("Listbox",NULL,WS_TABSTOP|WS_VISIBLE|WS_CHILD|LBS_NOTIFY|
LBS_WRAP|LBS_HASSTRINGS|LBS_OWNERDRAWFIXED|LBS_WANTKEYBOARDINPUT,
340,125,310,42*7,menuWnd,(HMENU)IDC_MAINMENU_MENU,NULL,NULL);
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"数字电视");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"广播节目");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"视频点播");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"游戏");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"短信");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"频道搜索");
SendMessage(menu,LB_ADDSTRING,0,(LPARAM)"系统设置");
SendMessage(menu,LB_SETITEMHEIGHT,0,42);
SendMessage(menu,LB_SETCURSEL,0,0);
...{
TBBUTTON toolbarBtns[] = ...{
...{0, 0, 0, BTNS_SEP, ...{0, 0}, 0, 0},
...{0, 123, TBSTATE_ENABLED,BTNS_BUTTON, ...{0, 0}, 0, "选择"},
...{1, 122, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0,"[确认]进入下级菜单"},
...{2, 133, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, "Test"},
...{3, 144, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
};
HWND htoolbar=CreateToolbarEx(menuWnd, WS_CHILD|WS_VISIBLE|
TBSTYLE_LIST|TBSTYLE_TRANSPARENT|TBSTYLE_FLAT|CCS_BOTTOM,
1234, 2, hInstDVBRes, IDB_ARROWKEYS, toolbarBtns,
sizeof(toolbarBtns)/sizeof(TBBUTTON),32, 16, 32, 16, sizeof(TBBUTTON));
SendMessage(htoolbar,TB_SETEXTENDEDSTYLE,0, TBSTYLE_EX_DRAWDDARROWS);
}
ShowWindow(menuWnd,SW_SHOW);
return menuWnd;
}