#include <windows.h>
#include "resource.h"
#define IDC_LIST 1
#define IDC_STATIC 2
#define LBTEXTSIZE 20
HWND hwndListBox,hwndStatic;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL ListBoxDraw(HWND hwnd, UINT uCtrlId, DRAWITEMSTRUCT *dis);
BOOL StaticDraw(HWND hwnd, UINT uCtrlId, DRAWITEMSTRUCT *dis);
HBITMAP hbmpPicture,hbmOld;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
MSG msg;
wc.cbSize        = sizeof(WNDCLASSEX);
wc.style         = 0;
wc.lpfnWndProc   = WndProc;
wc.cbClsExtra    = 0;
wc.cbWndExtra    = 0;
wc.hInstance     = hInstance;
wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName  = NULL;
wc.lpszClassName = TEXT("myWindowClass");
wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);


CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("myWindowClass"),TEXT("owner drawn control"), WS_VISIBLE | WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 660, 250, NULL, NULL, hInstance, NULL);

while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg)
{
PMEASUREITEMSTRUCT pmis; 
case WM_CREATE:
{
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
//create customised listbox by using using LB_OWNERDRAWFIXED flag
hwndListBox = CreateWindow(TEXT("ListBox"), TEXT(""), WS_CHILD | WS_VISIBLE | LBS_OWNERDRAWFIXED| LBS_OWNERDRAWVARIABLE|LBS_HASSTRINGS|LBS_NOTIFY| WS_BORDER | WS_VSCROLL, 10, 10, 300, 240, hwnd, (HMENU) IDC_LIST, NULL, NULL);
//create customised static box by using using SS_OWNERDRAW flag   
hwndStatic = CreateWindow(TEXT("static"), TEXT(""),WS_CHILD | WS_VISIBLE | SS_OWNERDRAW| WS_BORDER ,330, 10, 250, 70, hwnd, (HMENU) IDC_STATIC , hInstance, NULL);    

// populate listbox
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM) "chilli");
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM) "mushroom");
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM) "onion");
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM) "pineapple"); 
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM) "strawberry"); 
//add images to listbox from resource
hbmpPicture = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
SendMessage(hwndListBox, LB_SETITEMDATA, (WPARAM)0, (LPARAM)hbmpPicture);
hbmpPicture = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
SendMessage(hwndListBox, LB_SETITEMDATA, (WPARAM)1, (LPARAM)hbmpPicture);
hbmpPicture = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP3));
SendMessage(hwndListBox, LB_SETITEMDATA, (WPARAM)2, (LPARAM)hbmpPicture);
hbmpPicture = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
SendMessage(hwndListBox, LB_SETITEMDATA, (WPARAM)3, (LPARAM)hbmpPicture);
hbmpPicture = LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP5));
SendMessage(hwndListBox, LB_SETITEMDATA, (WPARAM)4, (LPARAM)hbmpPicture); 
       
break;
}        
        
case WM_COMMAND:
//responds to selection change
if (HIWORD(wParam) == LBN_SELCHANGE) {
HWND hwndCombo = GetDlgItem(hwnd, IDC_LIST);
TCHAR value[LBTEXTSIZE]=TEXT("\0");
int sel = (int) SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
hbmpPicture = (HBITMAP)SendMessage(hwndCombo,  LB_GETITEMDATA,sel, 0);
SendMessage(hwndListBox, LB_GETTEXT, sel,(LPARAM)value); 
SendMessage(hwndStatic, WM_SETTEXT, NULL,(LPARAM)value);
}
break;

//The WM_DRAWITEM message is sent to the parent window of an owner-drawn button when a visual aspect of that control has been changed.
case WM_DRAWITEM:
if(wParam == IDC_LIST) //for listbox
{    
ListBoxDraw(hwnd, wParam, (DRAWITEMSTRUCT *)lParam);
} 

if(wParam ==IDC_STATIC)//for button
{
StaticDraw(hwnd, wParam, (DRAWITEMSTRUCT *)lParam);
}

//WM_MEASUREITEM send to the owner window of a control when the control is created.
case WM_MEASUREITEM:  
pmis = (PMEASUREITEMSTRUCT) lParam; 
pmis->itemHeight = 60;//contains the item height of the owner-drawn listview item. 
return TRUE; 

case WM_DESTROY:
{
DeleteObject(hbmpPicture);
DeleteObject(hbmOld);
PostQuitMessage(0);
return 0;
}
}
    
return DefWindowProc(hwnd, msg, wParam, lParam);
}

//draw customised listbox
BOOL ListBoxDraw(HWND hwnd, UINT uCtrlId, DRAWITEMSTRUCT *dis)
{	
//HWND hwndCombo = GetDlgItem(hwnd, uCtrlId);
TCHAR lbText[LBTEXTSIZE];    
switch(dis->itemAction)
{
case ODA_SELECT:        
case ODA_DRAWENTIRE:
//set selected item state
if(dis->itemState & ODS_SELECTED)
{
SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
SetBkColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHT));
}
else
{
SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(dis->hDC, GetSysColor(COLOR_WINDOW));
}
//set listbox characteristics including font
HDC hdcMem = CreateCompatibleDC(dis->hDC);
HFONT font;
font = CreateFontA(30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Ariel");
TEXTMETRIC tm;
GetTextMetrics(dis->hDC,&tm);
SelectObject(dis->hDC,font);
//set listbox contents
SendMessage(hwndListBox, LB_GETTEXT, dis->itemID, (LONG)lbText);    
hbmpPicture = (HBITMAP)SendMessage(dis->hwndItem,  LB_GETITEMDATA,dis->itemID, 0); 
ExtTextOut(dis->hDC, 80 , dis->rcItem.top+20, ETO_OPAQUE, &dis->rcItem, lbText, lstrlen(lbText), 0);
hbmOld=(HBITMAP)SelectObject(hdcMem, hbmpPicture);
BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top+10, dis->rcItem.right - dis->rcItem.left, dis->rcItem.bottom - dis->rcItem.top, hdcMem, 0, 0, SRCAND);
DeleteDC(hdcMem);
DeleteObject(font);
hbmpPicture=NULL;        
break;
}
return TRUE;
}


BOOL StaticDraw(HWND hwnd, UINT uCtrlId, DRAWITEMSTRUCT *dis)
{
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
//HWND hwndCombo = GetDlgItem(hwnd, uCtrlId);

TCHAR lbText[LBTEXTSIZE];    
switch(dis->itemAction)
{    
case ODA_SELECT:        
case ODA_DRAWENTIRE:

//set static box font 
TEXTMETRIC tm;
HFONT font;
GetTextMetrics(dis->hDC,&tm);
font = CreateFontA(30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Ariel");
SelectObject(dis->hDC,font);

//set static box content
int sel = (int) SendMessageW(hwndListBox, LB_GETCURSEL, 0, 0);
hbmpPicture = (HBITMAP)SendMessage(hwndListBox,  LB_GETITEMDATA,sel, 0);
HDC hdcMem = CreateCompatibleDC(dis->hDC);
hbmOld=(HBITMAP)SelectObject(hdcMem, hbmpPicture);
SendMessage(hwndStatic, WM_GETTEXT,LBTEXTSIZE,(LONG)lbText);
ExtTextOut(dis->hDC, 75 ,20, ETO_OPAQUE, &dis->rcItem, lbText, lstrlen(lbText), 0);
BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top+10, dis->rcItem.right - dis->rcItem.left, dis->rcItem.bottom - dis->rcItem.top, hdcMem, 0, 0, SRCAND);
DeleteObject(font);
DeleteDC(hdcMem);
break;
}
return TRUE;
}