📄 combo.c
字号:
{
if( lphc->wState & CBF_CAPTURE )
{
lphc->wState &= ~CBF_CAPTURE;
if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
{
INT index = CBUpdateLBox( lphc, TRUE );
/* Update edit only if item is in the list */
if(index >= 0)
{
lphc->wState |= CBF_NOLBSELECT;
CBUpdateEdit( lphc, index );
lphc->wState &= ~CBF_NOLBSELECT;
}
}
ReleaseCapture();
SetCapture(lphc->hWndLBox);
}
if( lphc->wState & CBF_BUTTONDOWN )
{
lphc->wState &= ~CBF_BUTTONDOWN;
CBRepaintButton( lphc );
}
}
/***********************************************************************
* COMBO_MouseMove
*
* Two things to do - track combo button and release capture when
* pointer goes into the listbox.
*/
static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam )
{
POINT pt;
RECT lbRect;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
if( lphc->wState & CBF_BUTTONDOWN )
{
BOOL bButton;
bButton = PtInRect(&lphc->buttonRect, pt);
if( !bButton )
{
lphc->wState &= ~CBF_BUTTONDOWN;
CBRepaintButton( lphc );
}
}
GetClientRect( lphc->hWndLBox, &lbRect );
MapWindowPoints( lphc->self, lphc->hWndLBox, &pt, 1 );
if( PtInRect(&lbRect, pt) )
{
lphc->wState &= ~CBF_CAPTURE;
ReleaseCapture();
if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc, TRUE );
/* hand over pointer tracking */
SendMessageW(lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam);
}
}
static LRESULT COMBO_GetComboBoxInfo(LPHEADCOMBO lphc, COMBOBOXINFO *pcbi)
{
if (!pcbi || (pcbi->cbSize < sizeof(COMBOBOXINFO)))
return FALSE;
pcbi->rcItem = lphc->textRect;
pcbi->rcButton = lphc->buttonRect;
pcbi->stateButton = 0;
if (lphc->wState & CBF_BUTTONDOWN)
pcbi->stateButton |= STATE_SYSTEM_PRESSED;
if (IsRectEmpty(&lphc->buttonRect))
pcbi->stateButton |= STATE_SYSTEM_INVISIBLE;
pcbi->hwndCombo = lphc->self;
pcbi->hwndItem = lphc->hWndEdit;
pcbi->hwndList = lphc->hWndLBox;
return TRUE;
}
static char *strdupA(LPCSTR str)
{
char *ret;
DWORD len;
if(!str) return NULL;
len = strlen(str);
ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
memcpy(ret, str, len + 1);
return ret;
}
/***********************************************************************
* ComboWndProc_common
*
* http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
*/
static LRESULT ComboWndProc_common( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam, BOOL unicode )
{
LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
TRACE("[%p]: msg %s wp %08x lp %08lx\n",
hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
if( lphc || message == WM_NCCREATE )
switch(message)
{
/* System messages */
case WM_NCCREATE:
{
LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style :
((LPCREATESTRUCTA)lParam)->style;
return COMBO_NCCreate(hwnd, style);
}
case WM_NCDESTROY:
COMBO_NCDestroy(lphc);
break;/* -> DefWindowProc */
case WM_CREATE:
{
HWND hwndParent;
LONG style;
if(unicode)
{
hwndParent = ((LPCREATESTRUCTW)lParam)->hwndParent;
style = ((LPCREATESTRUCTW)lParam)->style;
}
else
{
hwndParent = ((LPCREATESTRUCTA)lParam)->hwndParent;
style = ((LPCREATESTRUCTA)lParam)->style;
}
return COMBO_Create(hwnd, lphc, hwndParent, style, unicode);
}
case WM_PRINTCLIENT:
/* Fallthrough */
case WM_PAINT:
/* wParam may contain a valid HDC! */
return COMBO_Paint(lphc, (HDC)wParam);
case WM_ERASEBKGND:
/* do all painting in WM_PAINT like Windows does */
return 1;
case WM_GETDLGCODE:
{
LRESULT result = DLGC_WANTARROWS | DLGC_WANTCHARS;
if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
{
int vk = (int)((LPMSG)lParam)->wParam;
if ((vk == VK_RETURN || vk == VK_ESCAPE) && (lphc->wState & CBF_DROPPED))
result |= DLGC_WANTMESSAGE;
}
return result;
}
case WM_WINDOWPOSCHANGING:
return COMBO_WindowPosChanging(hwnd, lphc, (LPWINDOWPOS)lParam);
case WM_WINDOWPOSCHANGED:
/* SetWindowPos can be called on a Combobox to resize its Listbox.
* In that case, the Combobox itself will not be resized, so we won't
* get a WM_SIZE. Since we still want to update the Listbox, we have to
* do it here.
*/
/* we should not force repainting on WM_WINDOWPOSCHANGED, it breaks
* Z-order based painting.
*/
/* fall through */
case WM_SIZE:
if( lphc->hWndLBox &&
!(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc, message == WM_SIZE );
return TRUE;
case WM_SETFONT:
COMBO_Font( lphc, (HFONT)wParam, (BOOL)lParam );
return TRUE;
case WM_GETFONT:
return (LRESULT)lphc->hFont;
case WM_SETFOCUS:
if( lphc->wState & CBF_EDIT )
SetFocus( lphc->hWndEdit );
else
COMBO_SetFocus( lphc );
return TRUE;
case WM_KILLFOCUS:
{
#ifdef __REACTOS__
HWND hwndFocus = (HWND)wParam;
#else
HWND hwndFocus = WIN_GetFullHandle( (HWND)wParam );
#endif
if( !hwndFocus ||
(hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
COMBO_KillFocus( lphc );
return TRUE;
}
case WM_COMMAND:
#ifdef __REACTOS__
return COMBO_Command( lphc, wParam, (HWND)lParam);
#else
return COMBO_Command( lphc, wParam, WIN_GetFullHandle( (HWND)lParam ) );
#endif
case WM_GETTEXT:
return unicode ? COMBO_GetTextW( lphc, wParam, (LPWSTR)lParam )
: COMBO_GetTextA( lphc, wParam, (LPSTR)lParam );
case WM_SETTEXT:
case WM_GETTEXTLENGTH:
case WM_CLEAR:
if ((message == WM_GETTEXTLENGTH) && !ISWIN31 && !(lphc->wState & CBF_EDIT))
{
int j = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
if (j == -1) return 0;
return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, j, 0) :
SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, j, 0);
}
else if( lphc->wState & CBF_EDIT )
{
LRESULT ret;
lphc->wState |= CBF_NOEDITNOTIFY;
ret = unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
SendMessageA(lphc->hWndEdit, message, wParam, lParam);
lphc->wState &= ~CBF_NOEDITNOTIFY;
return ret;
}
else return CB_ERR;
case WM_CUT:
case WM_PASTE:
case WM_COPY:
if( lphc->wState & CBF_EDIT )
{
return unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
SendMessageA(lphc->hWndEdit, message, wParam, lParam);
}
else return CB_ERR;
case WM_DRAWITEM:
case WM_DELETEITEM:
case WM_COMPAREITEM:
case WM_MEASUREITEM:
return COMBO_ItemOp(lphc, message, lParam);
case WM_ENABLE:
if( lphc->wState & CBF_EDIT )
EnableWindow( lphc->hWndEdit, (BOOL)wParam );
EnableWindow( lphc->hWndLBox, (BOOL)wParam );
/* Force the control to repaint when the enabled state changes. */
InvalidateRect(lphc->self, NULL, TRUE);
return TRUE;
case WM_SETREDRAW:
if( wParam )
lphc->wState &= ~CBF_NOREDRAW;
else
lphc->wState |= CBF_NOREDRAW;
if( lphc->wState & CBF_EDIT )
SendMessageW(lphc->hWndEdit, message, wParam, lParam);
SendMessageW(lphc->hWndLBox, message, wParam, lParam);
return 0;
case WM_SYSKEYDOWN:
if( KEYDATA_ALT & HIWORD(lParam) )
if( wParam == VK_UP || wParam == VK_DOWN )
COMBO_FlipListbox( lphc, FALSE, FALSE );
return 0;
case WM_CHAR:
case WM_IME_CHAR:
case WM_KEYDOWN:
{
HWND hwndTarget;
if ((wParam == VK_RETURN || wParam == VK_ESCAPE) &&
(lphc->wState & CBF_DROPPED))
{
CBRollUp( lphc, wParam == VK_RETURN, FALSE );
return TRUE;
}
else if ((wParam == VK_F4) && !(lphc->wState & CBF_EUI))
{
COMBO_FlipListbox( lphc, FALSE, FALSE );
return TRUE;
}
if( lphc->wState & CBF_EDIT )
hwndTarget = lphc->hWndEdit;
else
hwndTarget = lphc->hWndLBox;
return unicode ? SendMessageW(hwndTarget, message, wParam, lParam) :
SendMessageA(hwndTarget, message, wParam, lParam);
}
case WM_LBUTTONDOWN:
if( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self );
if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
return TRUE;
case WM_LBUTTONUP:
COMBO_LButtonUp( lphc );
return TRUE;
case WM_MOUSEMOVE:
if( lphc->wState & CBF_CAPTURE )
COMBO_MouseMove( lphc, wParam, lParam );
return TRUE;
case WM_MOUSEWHEEL:
if (wParam & (MK_SHIFT | MK_CONTROL))
return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
DefWindowProcA(hwnd, message, wParam, lParam);
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_UP, 0);
if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0);
return TRUE;
/* Combo messages */
#ifndef __REACTOS__
case CB_ADDSTRING16:
if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam);
/* fall through */
#endif
case CB_ADDSTRING:
if( unicode )
{
if( lphc->dwStyle & CBS_LOWERCASE )
CharLowerW((LPWSTR)lParam);
else if( lphc->dwStyle & CBS_UPPERCASE )
CharUpperW((LPWSTR)lParam);
return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
}
else /* unlike the unicode version, the ansi version does not overwrite
the string if converting case */
{
char *string = NULL;
LRESULT ret;
if( lphc->dwStyle & CBS_LOWERCASE )
{
string = strdupA((LPSTR)lParam);
CharLowerA(string);
}
else if( lphc->dwStyle & CBS_UPPERCASE )
{
string = strdupA((LPSTR)lParam);
CharUpperA(string);
}
ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
HeapFree(GetProcessHeap(), 0, string);
return ret;
}
#ifndef __REACTOS__
case CB_INSERTSTRING16:
wParam = (INT)(INT16)wParam;
if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam);
/* fall through */
#endif
case CB_INSERTSTRING:
if( unicode )
{
if( lphc->dwStyle & CBS_LOWERCASE )
CharLowerW((LPWSTR)lParam);
else if( lphc->dwStyle & CBS_UPPERCASE )
CharUpperW((LPWSTR)lParam);
return SendMessageW(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
}
else
{
if( lphc->dwStyle & CBS_LOWERCASE )
CharLowerA((LPSTR)lParam);
else if( lphc->dwStyle & CBS_UPPERCASE )
CharUpperA((LPSTR)lParam);
return SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
}
#ifndef __REACTOS__
case CB_DELETESTRING16:
#endif
case CB_DELETESTRING:
return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
#ifndef __REACTOS__
case CB_SELECTSTRING16:
wParam = (INT)(INT16)wParam;
if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam);
/* fall through */
#endif
case CB_SELECTSTRING:
return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
#ifndef __REACTOS__
case CB_FINDSTRING16:
wParam = (INT)(INT16)wParam;
if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam);
/* fall through */
#endif
case CB_FINDSTRING:
return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
#ifndef __REACTOS__
case CB_FINDSTRINGEXACT16:
wParam = (INT)(INT16)wParam;
if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)MapSL(lParam);
/* fall through */
#endif
case CB_FINDSTRINGEXACT:
return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam);
#ifndef __REACTOS__
case CB_SETITEMHEIGHT16:
wParam = (INT)(INT16)wParam; /* signed integer */
/* fall through */
#endif
case CB_SETITEMHEIGHT:
return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
#ifndef __REACTOS__
case CB_GETITEMHEIGHT16:
wParam = (INT)(INT16)wParam;
/* fall through */
#endif
case CB_GETITEMHEIGHT:
if( (INT)wParam >= 0 ) /* listbox item */
return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
return CBGetTextAreaHeight(hwnd, lphc);
#ifndef __REACTOS__
case CB_RESETCONTENT16:
#endif
case CB_RESETCONTENT:
SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) )
{
static const WCHAR empty_st
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -