소유자가 그린 목록 상자를 만드는 방법
이 항목에서는 소유자가 그린 목록 상자를 구현하는 방법을 보여 줍니다.
이 항목의 C++ 코드 예에서는 소유자가 그린 항목 5개(4개의 그리기 도구 및 포크)가 포함된 목록 상자를 그리는 방법을 보여 줍니다. 각 목록 항목은 개체 이름이 뒤에 오는 비트맵으로 나타납니다. 단추는 사용자에게 다른 항목과 다른 하나의 항목을 선택하라는 메시지를 표시합니다. 포크가 선택된 상태에서 단추를 선택하면 "You're right!"이라는 메시지가 표시됩니다. 메시지를 표시하고 대화 상자를 닫습니다. 다른 목록 항목이 선택된 상태에서 단추를 선택하면 "Try again!" 메시지가 표시됩니다.
목록 상자에는 표준 목록 상자 스타일 외에도 LBS_OWNERDRAWFIXED 및 LBS_HASSTRINGS 스타일이 있습니다.
알아야 하는 작업
기술
필수 구성 요소
- C/C++
- Windows 사용자 인터페이스 프로그래밍
지침
소유자가 그린 목록 상자를 초기화하려면 애플리케이션에서 각 목록 상자 항목에 대한 텍스트 문자열 및 관련 비트맵을 로드해야 합니다.
다음 C++ 코드 예에서 대화 상자 프로시저는 텍스트를 설정하기 위해 LB_ADDSTRING 메시지를 전송하여 IDC_LIST_STUFF 목록 상자를 초기화한 다음 LB_SETITEMDATA 메시지는 비트맵을 각 목록 상자 항목과 연결합니다. 또한 이 코드는 WM_MEASUREITEM 메시지를 처리하여 각 목록 상자 항목의 높이를 설정하고, WM_DRAWITEM 메시지를 처리하여 각 항목의 텍스트와 비트맵을 그립니다.
#define XBITMAP 48
#define YBITMAP 48
#define BUFFER MAX_PATH
HBITMAP hbmpPencil, hbmpCrayon, hbmpMarker, hbmpPen, hbmpFork;
HBITMAP hbmpPicture, hbmpOld;
void AddItem(HWND hwnd, PTSTR pstr, HBITMAP hbmp)
{
int lbItem;
lbItem = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)pstr);
SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)lbItem, (LPARAM)hbmp);
}
INT_PTR CALLBACK DlgDrawProc(HWND hDlg, UINT message,
UINT wParam, LONG lParam)
{
HWND hListBox;
PMEASUREITEMSTRUCT pmis;
PDRAWITEMSTRUCT pdis;
HDC hdcMem;
HBITMAP hbmp;
TCHAR achBuffer[BUFFER];
size_t cch;
int yPos;
int lbItem;
TEXTMETRIC tm;
RECT rcBitmap;
HRESULT hr;
switch (message)
{
case WM_INITDIALOG:
// Load the bitmaps. g_hInst is the global HINSTANCE handle.
hbmpPencil = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_PENCIL));
hbmpCrayon = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_CRAYON));
hbmpMarker = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_MARKER));
hbmpPen = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_PEN));
hbmpFork = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_FORK));
// Retrieve the list box handle.
hListBox = GetDlgItem(hDlg, IDC_LIST_STUFF);
// Initialize the list box text and associate a bitmap
// with each list box item.
AddItem(hListBox, L"pencil", hbmpPencil);
AddItem(hListBox, L"crayon", hbmpCrayon);
AddItem(hListBox, L"marker", hbmpMarker);
AddItem(hListBox, L"pen", hbmpPen);
AddItem(hListBox, L"fork", hbmpFork);
SetFocus(hListBox);
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
return TRUE;
case WM_MEASUREITEM:
pmis = (PMEASUREITEMSTRUCT) lParam;
// Set the height of the list box items.
pmis->itemHeight = YBITMAP;
return TRUE;
case WM_DRAWITEM:
pdis = (PDRAWITEMSTRUCT) lParam;
// If there are no list box items, skip this message.
if (pdis->itemID == -1)
{
break;
}
// Draw the bitmap and text for the list box item. Draw a
// rectangle around the bitmap if it is selected.
switch (pdis->itemAction)
{
case ODA_SELECT:
case ODA_DRAWENTIRE:
// Draw the bitmap associated with the item.
//
// Get the item bitmap.
hbmpPicture = (HBITMAP)SendMessage(pdis->hwndItem,
LB_GETITEMDATA, pdis->itemID, 0);
// Create a compatible device context.
hdcMem = CreateCompatibleDC(pdis->hDC);
// Select the item bitmap into the compatible device
// context and save the old bitmap.
hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpPicture);
// Copy the bitmap into the compatible device context.
BitBlt(pdis->hDC,
pdis->rcItem.left, pdis->rcItem.top,
pdis->rcItem.right - pdis->rcItem.left,
pdis->rcItem.bottom - pdis->rcItem.top,
hdcMem, 0, 0, SRCCOPY);
// Draw the string associated with the item.
//
// Get the item string from the list box.
SendMessage(pdis->hwndItem, LB_GETTEXT,
pdis->itemID, (LPARAM)achBuffer);
// Get the metrics for the current font.
GetTextMetrics(pdis->hDC, &tm);
// Calculate the vertical position for the item string
// so that the string will be vertically centered in the
// item rectangle.
yPos = (pdis->rcItem.bottom + pdis->rcItem.top -
tm.tmHeight) / 2;
// Get the character length of the item string.
hr = StringCchLength(achBuffer, BUFFER, &cch);
if (FAILED(hr))
{
// TODO: Handle error.
}
// Draw the string in the item rectangle, leaving a six
// pixel gap between the item bitmap and the string.
TextOut(pdis->hDC, XBITMAP + 6, yPos, achBuffer, cch);
// Clean up.
SelectObject(hdcMem, hbmpOld);
DeleteDC(hdcMem);
// Is the item selected?
if (pdis->itemState & ODS_SELECTED)
{
// Set RECT coordinates to surround only the
// bitmap.
rcBitmap.left = pdis->rcItem.left;
rcBitmap.top = pdis->rcItem.top;
rcBitmap.right = pdis->rcItem.left + XBITMAP;
rcBitmap.bottom = pdis->rcItem.top + YBITMAP;
// Draw a rectangle around bitmap to indicate
// the selection.
DrawFocusRect(pdis->hDC, &rcBitmap);
}
break;
case ODA_FOCUS:
// Do not process focus changes. The focus caret
// (outline rectangle) indicates the selection.
// The IDOK button indicates the final
// selection.
break;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
// Get the selected item's text.
lbItem = SendMessage(GetDlgItem(hDlg, IDC_LIST_STUFF),
LB_GETCURSEL, 0, 0);
// Get the selected item's bitmap.
hbmp = (HBITMAP) SendMessage(GetDlgItem(hDlg, IDC_LIST_STUFF),
LB_GETITEMDATA, lbItem, 0);
// If the item is not the correct answer, tell the
// user to try again.
//
// If the item is the correct answer, congratulate
// the user and destroy the dialog box.
if (hbmp != hbmpFork)
{
MessageBox(hDlg, L"Try again!", L"Oops", MB_OK);
return FALSE;
}
else
{
MessageBox(hDlg, L"You're right!",
L"Congratulations.", MB_OK);
// Fall through.
}
case IDCANCEL:
// Destroy the dialog box.
EndDialog(hDlg, TRUE);
return TRUE;
default:
return FALSE;
}
case WM_DESTROY:
// Free the bitmap resources.
DeleteObject(hbmpPencil);
DeleteObject(hbmpCrayon);
DeleteObject(hbmpMarker);
DeleteObject(hbmpPen);
DeleteObject(hbmpFork);
return TRUE;
default:
return FALSE;
}
return FALSE;
}
관련 항목