// 重绘.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MY);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_MY;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindowEx(NULL, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
void _cdecl Trace(LPCSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
char szBuffer[1024*20];
int nBuf = _vsnprintf(szBuffer, sizeof(szBuffer), lpszFormat, args);
OutputDebugStringA(szBuffer);
va_end(args);
}
#define TRACE Trace
BOOL ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
{
DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
if(dwStyle == dwNewStyle)
return FALSE;
::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
if(nFlags != 0)
{
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
}
return TRUE;
}
BOOL ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
{
DWORD dwStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
if(dwStyle == dwNewStyle)
return FALSE;
::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewStyle);
if(nFlags != 0)
{
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
}
return TRUE;
}
void DrawGradientV(HDC hDC, COLORREF colorStart, COLORREF colorEnd, RECT& DrawRect )
{
//如果开始结束色相同,则使用绘制色块命令绘制
if (colorStart==colorEnd)
{
HBRUSH h_Brush=CreateSolidBrush(colorStart);
FillRect(hDC,&DrawRect,h_Brush);
DeleteObject(h_Brush);
return ;
}
//找到其实颜色和结束颜色之间的最大颜色值,决定渐变步长等
int r, g, b;
float rStep, gStep, bStep;
r = (GetRValue(colorEnd) - GetRValue(colorStart));
g = (GetGValue(colorEnd) - GetGValue(colorStart));
b = (GetBValue(colorEnd) - GetBValue(colorStart));
int nSteps = max(abs(r), max(abs(g), abs(b)));
nSteps=DrawRect.bottom-DrawRect.top;
//计算每个颜色的步长
rStep = abs(r/(float)nSteps);
gStep = abs(g/(float)nSteps);
bStep = abs(b/(float)nSteps);
int r1,g1,b1;
r1 = GetRValue(colorStart);
g1 = GetGValue(colorStart);
b1 = GetBValue(colorStart);
//准备GDI
HDC hMemDC=CreateCompatibleDC(hDC); //创建内存DC
HBITMAP hBitmap=::CreateCompatibleBitmap(hDC,1,nSteps);//创建位图
::SelectObject(hMemDC,hBitmap); //把位图选进内存DC
for(int i = 0; i<nSteps ; i ++ )
{
SetPixel(hMemDC,0,i,RGB( r1+r*i/nSteps, g1+g*i/nSteps, b1+b*i/nSteps));
}
//内存DC映射到屏幕DC
StretchBlt(hDC, DrawRect.left,DrawRect.top,DrawRect.right-DrawRect.left,DrawRect.bottom-DrawRect.top,hMemDC,0,0,1,nSteps,SRCCOPY);
//删除
::DeleteDC(hMemDC);
::DeleteObject(hBitmap);
}
HWND hwListbox=NULL;
WNDPROC old_ListBox_WndProc=NULL;
LRESULT CALLBACK ListBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//TRACE("message:%08X", message);
if (message == WM_ERASEBKGND)
{
return TRUE;
}
return CallWindowProc(old_ListBox_WndProc,hWnd,message,wParam,lParam);
}
HWND CreateListBox(HWND hParent)
{
HWND hList=::CreateWindowEx( NULL, "ListBox",
NULL,
WS_CHILD|WS_VSCROLL|WS_VISIBLE|LBS_NOTIFY|LBS_HASSTRINGS|LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWVARIABLE,
10,10,300,300,
hParent,
(HMENU)0x1000,
hInst,
NULL);
old_ListBox_WndProc=(WNDPROC)::SetWindowLong(hList,GWL_WNDPROC,(LONG)ListBox_WndProc);
int i;
char text[256];
for (i=0;i<1000;i++)
{
sprintf(text,"list item %d", i);
ListBox_AddString(hList, text);
}
for (i=0;i<1000;i++)
{
ListBox_SetItemHeight(hList,i,30);
}
return hList;
}
BOOL OnDrawListBox(LPDRAWITEMSTRUCT lpdis)
{
if (lpdis->itemState & ODS_SELECTED)
{
DrawGradientV(lpdis->hDC,0xffcccc,0xcc9999,lpdis->rcItem);
}else{
HBRUSH hBrush=::CreateSolidBrush(0xFEF5EA);
FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);
DeleteObject(hBrush);
}
char buff[256];
ListBox_GetText(lpdis->hwndItem,lpdis->itemID,buff);
SIZE s;
GetTextExtentPoint32(lpdis->hDC," ", 1, &s);
RECT drc=lpdis->rcItem;
drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
drc.bottom=drc.top+s.cy;
drc.left+=s.cy/2;
SetBkMode(lpdis->hDC, TRANSPARENT);
DrawText(lpdis->hDC,buff,strlen(buff),&drc,DT_LEFT|DT_VCENTER);
return TRUE;
}
HWND hwComboBox=NULL;
WNDPROC old_ComboBox_WndProc=NULL;
WNDPROC old_ComboBox_ListBox_WndProc=NULL;
LRESULT CALLBACK ComboBox_ListBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_ERASEBKGND) return TRUE;
return CallWindowProc(old_ComboBox_ListBox_WndProc,hWnd,message,wParam,lParam);
}
LRESULT CALLBACK ComboBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
if (message == WM_ERASEBKGND) return TRUE;
if (message == WM_PAINT)
{
hdc = BeginPaint(hWnd, &ps);
DRAWITEMSTRUCT drawItem;
memset(&drawItem,0,sizeof(drawItem));
drawItem.hDC=hdc;
drawItem.hwndItem=hWnd;
GetClientRect(hWnd,&drawItem.rcItem);
drawItem.CtlID=GetWindowLong(hWnd,GWL_ID);
if (::GetKeyState(VK_LBUTTON) & 0x80)
{
drawItem.itemState=1;
}
drawItem.itemID=-1;
SendMessage(GetParent(hWnd),WM_DRAWITEM,0,(LPARAM)&drawItem);
EndPaint(hWnd, &ps);
return TRUE;
}
return CallWindowProc(old_ComboBox_WndProc,hWnd,message,wParam,lParam);
}
HWND CreateComboBox(HWND hParent)
{
HWND hComboBox=::CreateWindowEx( NULL, "ComboBox",
NULL,
WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|CBS_DISABLENOSCROLL|CBS_NOINTEGRALHEIGHT|CBS_OWNERDRAWVARIABLE,
320,10,300,320,
hParent,
(HMENU)0x1001,
hInst,
NULL);
old_ComboBox_WndProc=(WNDPROC)SetWindowLong(hComboBox,GWL_WNDPROC,(LONG)ComboBox_WndProc);
COMBOBOXINFO cbi= { sizeof(COMBOBOXINFO) };
if (GetComboBoxInfo(hComboBox,&cbi))
{
//TRACE("hComboBox:%08X cbi.hwndCombo:%08X cbi.hwndItem:%08X cbi.hwndList:%08X", hComboBox, cbi.hwndCombo, cbi.hwndItem, cbi.hwndList);
ModifyStyle(cbi.hwndList,WS_BORDER,0,0);
ModifyStyleEx(cbi.hwndList,WS_EX_CLIENTEDGE,0,0);
old_ComboBox_ListBox_WndProc=(WNDPROC)SetWindowLong(cbi.hwndList,GWL_WNDPROC,(LONG)ComboBox_ListBox_WndProc);
}
int i;
char text[256];
for (i=0;i<1000;i++)
{
sprintf(text,"list item %d", i);
ComboBox_AddString(hComboBox, text);
}
ComboBox_SetItemHeight(hComboBox,-1,20);
for (i=0;i<1000;i++)
{
ComboBox_SetItemHeight(hComboBox,i,30);
}
return hComboBox;
}
BOOL OnDrawComboBox(LPDRAWITEMSTRUCT lpdis)
{
char buff[256]={0};
//绘制ComboBox控件
if (lpdis->itemID==-1)
{
//读取但前选择的文字
int icur=ComboBox_GetCurSel(lpdis->hwndItem);
if (icur!=-1)
{
ComboBox_GetLBText(lpdis->hwndItem,icur,buff);
}
//绘制ComboBox背景
HBRUSH hBrush;
if (lpdis->itemState==2)
{
hBrush=::CreateSolidBrush(0xFBEDDF);
}else{
hBrush=::CreateSolidBrush(0xFEF5EA);
}
FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);
DeleteObject(hBrush);
//绘制文字
SIZE s;
GetTextExtentPoint32(lpdis->hDC," ", 1, &s);
RECT drc=lpdis->rcItem;
drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
drc.bottom=drc.top+s.cy;
drc.left+=s.cy/2;
int slen=strlen(buff);
if (slen)
{
SetBkMode(lpdis->hDC, TRANSPARENT);
DrawText(lpdis->hDC,buff,slen,&drc,DT_LEFT|DT_VCENTER);
}
//绘制ListBox背景
}else{
if (lpdis->itemState & ODS_SELECTED)
{
DrawGradientV(lpdis->hDC,0xffcccc,0xcc9999,lpdis->rcItem);
}else{
HBRUSH hBrush=::CreateSolidBrush(0xFEF5EA); //0xFBEDDF
FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);
DeleteObject(hBrush);
}
ComboBox_GetLBText(lpdis->hwndItem,lpdis->itemID,buff);
//绘制文字
SIZE s;
GetTextExtentPoint32(lpdis->hDC," ", 1, &s);
RECT drc=lpdis->rcItem;
drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
drc.bottom=drc.top+s.cy;
drc.left+=s.cy/2;
int slen=strlen(buff);
if (slen)
{
SetBkMode(lpdis->hDC, TRANSPARENT);
DrawText(lpdis->hDC,buff,slen,&drc,DT_LEFT|DT_VCENTER);
}
}
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_CREATE:
{
hwListbox = CreateListBox(hWnd);
hwComboBox = CreateComboBox(hWnd);
return TRUE;
}
break;
case WM_CTLCOLORLISTBOX:
{
//TRACE("WM_CTLCOLORLISTBOX");
}
break;
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT)lParam;
if (lpdis->CtlID==0x1000)
{
if (OnDrawListBox(lpdis)) return TRUE;
}else if (lpdis->CtlID==0x1001){
if (OnDrawComboBox(lpdis)) return TRUE;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}