Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

539 lines
14 KiB

#include "trackbar.h"
#include <windowsx.h>
#include "comboex.h"
#include "ccport.h"
const TCHAR FAR c_szComboBox[] = TEXT("combobox");
const TCHAR FAR c_szComboBoxEx[] = TEXT("ComboBoxEx32");
#define MAXSTRLEN 256
#define COMBO_MARGIN 4
#define COMBO_WIDTH g_cxSmIcon
#define COMBO_HEIGHT g_cySmIcon
#define COMBO_BORDER 3
typedef struct {
CONTROLINFO ci;
HWND hwndCombo;
HIMAGELIST himl;
HFONT hFont;
int cxIndent;
BOOL fFontCreated:1;
} COMBOEX, *PCOMBOBOXEX;
typedef struct {
LPSTR pszText;
int iImage;
int iSelectedImage;
int iOverlay;
int iIndent;
LPARAM lParam;
} CEITEM, *PCEITEM;
BOOL ComboEx_OnGetItem(PCOMBOBOXEX pce, PCOMBOBOXEXITEM pceItem);
void ComboEx_DeleteFont(PCOMBOBOXEX pce)
{
if (pce->hFont && pce->fFontCreated) {
DeleteObject(pce->hFont);
pce->hFont = NULL;
}
}
void ComboEx_OnSetFont(PCOMBOBOXEX pce, HFONT hFont, BOOL fRedraw)
{
ComboEx_DeleteFont(pce);
if (!hFont) {
LOGFONT lf;
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
pce->hFont = CreateFontIndirect(&lf);
pce->fFontCreated = TRUE;
}
SendMessage(pce->hwndCombo, WM_SETFONT, (WPARAM)hFont, fRedraw);
}
void ComboEx_OnDestroy(PCOMBOBOXEX pce)
{
// don't need do destroy hwndCombo.. it will be destroyed along with us.
ComboEx_DeleteFont(pce);
LocalFree(pce);
}
BOOL ComboEx_OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
PCOMBOBOXEX pce;
DWORD dwStyle;
pce = (PCOMBOBOXEX)LocalAlloc(LPTR, sizeof(COMBOEX));
if (!pce)
return FALSE;
SetWindowInt(hwnd, 0, (LONG)pce);
CIInitialize(&pce->ci, hwnd, lpcs);
dwStyle = CBS_OWNERDRAWFIXED | WS_VISIBLE |WS_VSCROLL;
dwStyle |= (lpcs->style & (CBS_DROPDOWNLIST | CBS_SIMPLE |
CBS_NOINTEGRALHEIGHT | WS_CHILD));
pce->hwndCombo = CreateWindowEx(0, c_szComboBox, lpcs->lpszName,
dwStyle,
0, 0, lpcs->cx, lpcs->cy,
hwnd, lpcs->hMenu, lpcs->hInstance, 0);
if (!pce->hwndCombo) {
ComboEx_OnDestroy(pce);
return FALSE;
}
ComboEx_OnSetFont(pce, NULL, FALSE);
pce->cxIndent = 10;
// BUGBUG: force off borders off ourself
return TRUE;
}
HIMAGELIST ComboEx_OnSetImageList(PCOMBOBOXEX pce, HIMAGELIST himl)
{
HIMAGELIST himlOld = pce->himl;
pce->himl = himl;
InvalidateRect(pce->hwndCombo, NULL, TRUE);
return himlOld;
}
void ComboEx_OnDrawItem(PCOMBOBOXEX pce, LPDRAWITEMSTRUCT pdis)
{
HDC hdc = pdis->hDC;
RECT rc = pdis->rcItem;
TCHAR szText[MAXSTRLEN];
int offset = 0;
int xString, yString, xCombo;
int iLen;
SIZE sizeText;
COMBOBOXEXITEM cei;
if ((int)pdis->itemID < 0)
{
return;
}
cei.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_OVERLAY | CBEIF_SELECTEDIMAGE| CBEIF_INDENT;
cei.pszText = szText;
cei.cchTextMax = ARRAYSIZE(szText);
cei.iItem = pdis->itemID;
ComboEx_OnGetItem(pce, &cei);
// if we're not drawing the edit box, figure out how far to indent
// over
if (!(pdis->itemState & ODS_COMBOBOXEDIT))
{
offset = pce->cxIndent * cei.iIndent;
}
xCombo = rc.left + COMBO_BORDER + offset;
rc.left = xString = xCombo + COMBO_WIDTH + COMBO_MARGIN;
iLen = lstrlen(szText);
GetTextExtentPoint(hdc, szText, iLen, &sizeText);
rc.right = rc.left + sizeText.cx;
rc.left--;
rc.right++;
if (pdis->itemAction != ODA_FOCUS)
{
int yMid;
yMid = (rc.top + rc.bottom) / 2;
// center the string within rc
yString = yMid - (sizeText.cy/2);
SetBkColor(hdc, GetSysColor((pdis->itemState & ODS_SELECTED) ?
COLOR_HIGHLIGHT : COLOR_WINDOW));
SetTextColor(hdc, GetSysColor((pdis->itemState & ODS_SELECTED) ?
COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
if ((pdis->itemState & ODS_COMBOBOXEDIT) &&
(rc.right > pdis->rcItem.right))
{
// Need to clip as user does not!
rc.right = pdis->rcItem.right;
}
ExtTextOut(hdc, xString, yString, ETO_OPAQUE | ETO_CLIPPED, &rc, szText, iLen, NULL);
ImageList_Draw(pce->himl,
(pdis->itemState & ODS_SELECTED) ? cei.iSelectedImage : cei.iImage,
hdc, xCombo, yMid - (COMBO_HEIGHT/2),
INDEXTOOVERLAYMASK(cei.iOverlay) |
((pdis->itemState & ODS_SELECTED) ? (ILD_SELECTED | ILD_FOCUS) : ILD_NORMAL));
}
if (pdis->itemAction == ODA_FOCUS ||
(pdis->itemState & ODS_FOCUS))
{
DrawFocusRect(hdc, &rc);
}
}
void ComboEx_OnMeasureItem(PCOMBOBOXEX pce, LPMEASUREITEMSTRUCT pmi)
{
HDC hdc;
HFONT hfontOld;
int dyDriveItem;
SIZE siz;
hdc = GetDC(NULL);
hfontOld = SelectObject(hdc, pce->hFont);
GetTextExtentPoint(hdc, TEXT("W"), 1, &siz);
dyDriveItem = siz.cy;
if (hfontOld)
SelectObject(hdc, hfontOld);
ReleaseDC(NULL, hdc);
dyDriveItem += COMBO_BORDER;
if (dyDriveItem < COMBO_HEIGHT)
dyDriveItem = COMBO_HEIGHT;
pmi->itemHeight = dyDriveItem;
}
void ComboEx_ISetItem(PCOMBOBOXEX pce, PCEITEM pcei, PCOMBOBOXEXITEM pceItem)
{
if (pceItem->mask & CBEIF_INDENT)
pcei->iIndent = pceItem->iIndent;
if (pceItem->mask & CBEIF_IMAGE)
pcei->iImage = pceItem->iImage;
if (pceItem->mask & CBEIF_SELECTEDIMAGE)
pcei->iSelectedImage = pceItem->iSelectedImage;
if (pceItem->mask & CBEIF_OVERLAY)
pcei->iOverlay = pceItem->iOverlay;
if (pceItem->mask & CBEIF_TEXT) {
if (pcei->pszText == LPSTR_TEXTCALLBACK)
pcei->pszText = NULL;
Str_Set(&pcei->pszText, pceItem->pszText);
}
if (pceItem->mask & CBEIF_LPARAM) {
pcei->lParam = pceItem->lParam;
}
}
#define ComboEx_GetItemPtr(pce, iItem) \
((PCEITEM)SendMessage((pce)->hwndCombo, CB_GETITEMDATA, iItem, 0))
#define ComboEx_Count(pce) \
((int)SendMessage((pce)->hwndCombo, CB_GETCOUNT, 0, 0))
BOOL ComboEx_OnGetItem(PCOMBOBOXEX pce, PCOMBOBOXEXITEM pceItem)
{
PCEITEM pcei = ComboEx_GetItemPtr(pce, pceItem->iItem);
NMCOMBOBOXEX nm;
if (!pcei)
return FALSE;
nm.ceItem.mask = 0;
if (pceItem->mask & CBEIF_TEXT) {
if (pceItem->pszText == LPSTR_TEXTCALLBACK) {
nm.ceItem.mask |= CBEIF_TEXT;
} else {
Str_GetPtr(pcei->pszText, pceItem->pszText, pceItem->cchTextMax);
}
}
if (pceItem->mask & CBEIF_IMAGE) {
if (pceItem->iImage == I_IMAGECALLBACK) {
nm.ceItem.mask |= CBEIF_IMAGE;
}
pceItem->iImage = pcei->iImage;
}
if (pceItem->mask & CBEIF_SELECTEDIMAGE) {
if (pceItem->iSelectedImage == I_IMAGECALLBACK) {
nm.ceItem.mask |= CBEIF_SELECTEDIMAGE;
}
pceItem->iSelectedImage = pcei->iSelectedImage;
}
if (pceItem->mask & CBEIF_OVERLAY) {
if (pceItem->iOverlay == I_IMAGECALLBACK) {
nm.ceItem.mask |= CBEIF_OVERLAY;
}
pceItem->iOverlay = pcei->iOverlay;
}
if (pceItem->mask & CBEIF_INDENT) {
if (pceItem->iIndent == I_INDENTCALLBACK) {
nm.ceItem.mask |= CBEIF_INDENT;
pceItem->iIndent = 0;
} else {
pceItem->iIndent = pcei->iIndent;
}
}
if (pceItem->mask & CBEIF_LPARAM) {
pceItem->lParam = pcei->lParam;
}
// is there anything to call back for?
if (nm.ceItem.mask) {
UINT uMask = nm.ceItem.mask;
nm.ceItem = *pceItem;
nm.ceItem.lParam = pcei->lParam;
nm.ceItem.mask = uMask;
if ((nm.ceItem.mask & CBEIF_TEXT) &&
nm.ceItem.cchTextMax) {
// null terminate just in case they don't respond
*nm.ceItem.pszText = 0;
}
CCSendNotify(&pce->ci, CBEN_GETDISPINFO, &nm.hdr);
if (nm.ceItem.mask & CBEIF_INDENT)
pceItem->iIndent = nm.ceItem.iIndent;
if (nm.ceItem.mask & CBEIF_IMAGE)
pceItem->iImage = nm.ceItem.iImage;
if (nm.ceItem.mask & CBEIF_SELECTEDIMAGE)
pceItem->iSelectedImage = nm.ceItem.iSelectedImage;
if (nm.ceItem.mask & CBEIF_OVERLAY)
pceItem->iOverlay = nm.ceItem.iOverlay;
if (nm.ceItem.mask & CBEIF_TEXT)
pceItem->pszText = nm.ceItem.pszText;
if (nm.ceItem.mask & CBEIF_DI_SETITEM) {
ComboEx_ISetItem(pce, pcei, &nm.ceItem);
}
}
return TRUE;
}
BOOL ComboEx_OnSetItem(PCOMBOBOXEX pce, PCOMBOBOXEXITEM pceItem)
{
PCEITEM pcei = ComboEx_GetItemPtr(pce, pceItem->iItem);
UINT rdwFlags = 0;
ComboEx_ISetItem(pce, pcei, pceItem);
if (rdwFlags & (CBEIF_INDENT | CBEIF_IMAGE |CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_OVERLAY)) {
rdwFlags = RDW_ERASE | RDW_INVALIDATE;
}
// BUGBUG: do something better..
if (rdwFlags) {
RedrawWindow(pce->hwndCombo, NULL, NULL, rdwFlags);
}
// BUGUBG: notify item changed
return TRUE;
}
void ComboEx_HandleDeleteItem(PCOMBOBOXEX pce, LPDELETEITEMSTRUCT pdis)
{
PCEITEM pcei = (PCEITEM)pdis->itemData;
if (pcei) {
NMCOMBOBOXEX nm;
if (pcei->pszText && pcei->pszText != LPSTR_TEXTCALLBACK) {
Str_Set(&pcei->pszText, NULL);
}
nm.ceItem.iItem = pdis->itemID;
nm.ceItem.mask = CBEIF_LPARAM;
nm.ceItem.lParam = pcei->lParam;
CCSendNotify(&pce->ci, CBEN_DELETEITEM, &nm.hdr);
LocalFree(pcei);
}
}
int ComboEx_OnInsertItem(PCOMBOBOXEX pce, PCOMBOBOXEXITEM pceItem)
{
int iRet;
PCEITEM pcei = (PCEITEM)LocalAlloc(LPTR, sizeof(CEITEM));
if (!pcei)
return -1;
pcei->iImage = -1;
pcei->iSelectedImage = -1;
//pcei->iOverlay = 0;
//pcei->iIndent = 0;
ComboEx_ISetItem(pce, pcei, pceItem);
iRet = SendMessage(pce->hwndCombo, CB_INSERTSTRING, pceItem->iItem, (LPARAM)pcei);
if (iRet != -1) {
NMCOMBOBOXEX nm;
nm.ceItem = *pceItem;
CCSendNotify(&pce->ci, CBEN_INSERTITEM, &nm.hdr);
}
return iRet;
}
void ComboEx_OnSize(PCOMBOBOXEX pce)
{
if (pce) {
RECT rcWindow, rcClient;
RECT rc;
GetWindowRect(pce->ci.hwnd, &rcWindow);
GetClientRect(pce->ci.hwnd, &rcClient);
SetWindowPos(pce->hwndCombo, NULL, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
SWP_NOACTIVATE);
GetWindowRect(pce->hwndCombo, &rc);
SetWindowPos(pce->ci.hwnd, NULL, 0, 0,
RECTWIDTH(rc) + (RECTWIDTH(rcWindow) - RECTWIDTH(rcClient)),
RECTHEIGHT(rc) + (RECTHEIGHT(rcWindow) - RECTHEIGHT(rcClient)),
SWP_NOACTIVATE | SWP_NOMOVE);
}
}
LRESULT ComboEx_HandleCommand(PCOMBOBOXEX pce, WPARAM wParam, LPARAM lParam)
{
UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
UINT uCmd = GET_WM_COMMAND_CMD(wParam, lParam);
return SendMessage(pce->ci.hwndParent, WM_COMMAND, GET_WM_COMMAND_MPS(idCmd, pce->ci.hwnd, uCmd));
}
LRESULT CALLBACK ComboExWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PCOMBOBOXEX pce = (PCOMBOBOXEX)GetWindowInt(hwnd, 0);
switch (uMsg) {
HANDLE_MSG(pce, WM_SETFONT, ComboEx_OnSetFont);
case WM_CREATE:
return ComboEx_OnCreate(hwnd, (LPCREATESTRUCT)lParam);
case WM_DESTROY:
ComboEx_OnDestroy(pce);
break;
case WM_SIZE:
ComboEx_OnSize(pce);
break;
case WM_DRAWITEM:
ComboEx_OnDrawItem(pce, (LPDRAWITEMSTRUCT)lParam);
break;
case WM_MEASUREITEM:
ComboEx_OnMeasureItem(pce, (LPMEASUREITEMSTRUCT)lParam);
break;
case WM_COMMAND:
return ComboEx_HandleCommand(pce, wParam, lParam);
case WM_GETFONT:
return (LRESULT)pce->hFont;
case WM_DELETEITEM:
ComboEx_HandleDeleteItem(pce, (LPDELETEITEMSTRUCT)lParam);
return TRUE;
case CBEM_SETIMAGELIST:
return (LRESULT)ComboEx_OnSetImageList(pce, (HIMAGELIST)lParam);
case CBEM_GETIMAGELIST:
return (LRESULT)pce->himl;
case CBEM_GETITEM:
return ComboEx_OnGetItem(pce, (PCOMBOBOXEXITEM)lParam);
case CBEM_SETITEM:
return ComboEx_OnSetItem(pce, (PCOMBOBOXEXITEM)lParam);
case CBEM_INSERTITEM:
return ComboEx_OnInsertItem(pce, (PCOMBOBOXEXITEM)lParam);
case CB_LIMITTEXT:
break;
case CB_GETITEMDATA:
case CB_SETITEMDATA:
case CB_SETITEMHEIGHT:
case CB_INSERTSTRING:
case CB_ADDSTRING:
case CB_SETEDITSEL:
case CB_FINDSTRINGEXACT:
case CB_FINDSTRING:
case CB_DIR:
// override to do nothing
break;
case CB_SETCURSEL:
case CB_SHOWDROPDOWN:
case CB_SETEXTENDEDUI:
case CB_GETEXTENDEDUI:
case CB_GETDROPPEDSTATE:
case CB_GETDROPPEDCONTROLRECT:
case CB_GETCURSEL:
case CB_GETCOUNT:
case CB_SELECTSTRING:
case CB_RESETCONTENT:
case CB_DELETESTRING:
case CB_GETITEMHEIGHT:
return SendMessage(pce->hwndCombo, uMsg, wParam, lParam);
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
BOOL InitComboExClass(HINSTANCE hinst)
{
WNDCLASS wc;
if (!GetClassInfo(hinst, c_szComboBoxEx, &wc)) {
wc.lpfnWndProc = ComboExWndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.lpszMenuName = NULL;
wc.hInstance = hinst;
wc.lpszClassName = c_szComboBoxEx;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // NULL;
wc.style = CS_GLOBALCLASS;
wc.cbWndExtra = sizeof(PCOMBOBOXEX);
wc.cbClsExtra = 0;
return RegisterClass(&wc);
}
return TRUE;
}