ListView自绘OwnerDraw
1.ListView自绘OwnerDraw
正在试错是否使用了列表视图,尽量制作出智能的表格编辑器。本页显示了业主抽签的表格数据(二维数组数据)的显示方法。
显示画面和整个程序如下所示。使用ListView_GetSubItemRect宏的话,就不需要getRect函数了。
当nCol的值为0时得到的区域不是第一列,而是全列即整个行的区域。因为下面的程序是左对齐显示的,所以没有问题,但是要把显示放在中间或改变第1列的背景颜色的话,需要第1列的区域。为此,第1列的右端需要从第2列的左端进行修正。
Listview51.c
//ListView
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
#define NROW 12
#define NCOL 4
char *colname[NCOL] = { "No.", "Name", "Attr", "Age" };
char *table[NROW][NCOL] = {
{"01","张三","老大", "15"}, {"02","李四","老二","11"}, {"03","王五","老三","9"},
{"04","张三","老大", "15"}, {"05","李四","老二","11"}, {"06","王五","老三","9"},
{"07","张三","老大", "15"}, {"08","李四","老二","11"}, {"09","王五","老三","9"},
{"10","张三","老大", "15"}, {"11","李四","老二","11"}, {"12","王五","老三","9"},
};
HWND hList;
// ListView_GetSubItemRect(hwnd, nRow, nCol, LVIR_BOUNDS, pRect);
BOOL getRect(HWND hwnd, int nRow, int nCol, RECT *pRect) {
pRect->left = LVIR_BOUNDS;
pRect->top = nCol;
return (BOOL)SendMessage(hwnd, LVM_GETSUBITEMRECT, (WPARAM)nRow, (LPARAM)pRect);
}
// ListView的所有者抽签。行单位。
int onDrawItem(HWND hwnd, WPARAM wp, LPARAM lp) {
DRAWITEMSTRUCT *pds = (DRAWITEMSTRUCT *)lp;
if (pds->hwndItem == hList) {
int nCol, nRow = pds->itemID;
HDC hdc = pds->hDC;
for (nCol = 0; nCol < NCOL; nCol++) {
RECT rc;
getRect(hList, nRow, nCol, &rc);
rc.left += 4;
DrawText(hdc, table[nRow][nCol], -1, &rc, DT_VCENTER|DT_SINGLELINE|DT_LEFT);
}
}
return TRUE;
}
void onCreate(HWND hWnd) {
int iCol, iRow;
hList = CreateWindowEx(0, WC_LISTVIEW, NULL,
WS_CHILD|WS_VISIBLE|LVS_REPORT|LVS_OWNERDRAWFIXED,
0, 0, 1, 1, hWnd, (HMENU)777, NULL, NULL);
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);
for (iCol = 0; iCol < NCOL; iCol++) {
LVCOLUMN col = { LVCF_FMT|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM, 0,
70, colname[iCol], 0, iCol };
SendMessage(hList, LVM_INSERTCOLUMN, iCol, (LPARAM)&col);
}
for (iRow = 0; iRow < NROW; iRow++) {
LVITEM item = { LVIF_TEXT, iRow };
SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&item);
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
switch (umsg) {
case WM_CREATE: onCreate(hwnd); return 0;
case WM_DRAWITEM: return onDrawItem(hwnd, wp, lp);
case WM_SIZE: MoveWindow(hList, 0, 0, lp&0xffff, lp>>16, TRUE); return 0;
case WM_DESTROY: PostQuitMessage(0); return 0;
}
return DefWindowProc(hwnd, umsg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS wc = { 0, WindowProc, 0, 0, hInst, NULL, LoadCursor(NULL,IDC_ARROW), NULL, NULL, "mh" };
if (!RegisterClass(&wc)) return FALSE;
InitCommonControls();
if (!CreateWindowEx(0, "mh", "ListView", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
100, 100, 250, 200, NULL, NULL, hInst, NULL)) return FALSE;
while (GetMessage(&msg,NULL,0,0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}