* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * NOTES
- *
- * This code was audited for completeness against the documented features
- * of Comctl32.dll version 6.0 on Oct. 4, 2004, by Dimitrie O. Paun.
- *
- * Unless otherwise noted, we believe this code to be complete, as per
- * the specification mentioned above.
- * If you discover missing features, or bugs, please note them below.
- *
* TODO:
- * - ComboBox_[GS]etMinVisible()
- * - CB_GETMINVISIBLE, CB_SETMINVISIBLE
* - CB_SETTOPINDEX
*/
#include <user32.h>
-#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(combo);
/*
#define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
#define CB_HASSTRINGS( lphc ) ((lphc)->dwStyle & CBS_HASSTRINGS)
#define CB_HWND( lphc ) ((lphc)->self)
-// ReactOS already define in include/controls.h We have it here as a sync note.
-//#define CB_GETTYPE( lphc ) ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
+#ifndef __REACTOS__
+/* ReactOS already define in include/controls.h We have it here as a sync note. */
+#define CB_GETTYPE( lphc ) ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
+#endif
#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
{
comboboxW, /* name */
CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, /* style */
+#ifdef __REACTOS__
ComboWndProcA, /* procA */
ComboWndProcW, /* procW */
+#else
+ WINPROC_COMBO, /* proc */
+#endif
sizeof(HEADCOMBO *), /* extra */
IDC_ARROW, /* cursor */
0 /* brush */
return FALSE;
}
-
+#ifdef __REACTOS__
/* Retrieve the UI state for the control */
static BOOL COMBO_update_uistate(LPHEADCOMBO lphc)
{
lphc->UIState = DefWindowProcW(lphc->self, WM_QUERYUISTATE, 0, 0);
return prev_flags != lphc->UIState;
}
+#endif
/***********************************************************************
* COMBO_NCCreate
lphc->self = hwnd;
SetWindowLongPtrW( hwnd, 0, (LONG_PTR)lphc );
+#ifdef __REACTOS__
COMBO_update_uistate(lphc);
+#endif
/* some braindead apps do try to use scrollbar/border flags */
*/
static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
{
+ if (lphc)
+ {
+ TRACE("[%p]: freeing storage\n", lphc->self);
- if( lphc )
- {
- TRACE("[%p]: freeing storage\n", lphc->self);
-
- if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
- DestroyWindow( lphc->hWndLBox );
+ if ( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
+ DestroyWindow( lphc->hWndLBox );
- SetWindowLongPtrW( lphc->self, 0, 0 );
- HeapFree( GetProcessHeap(), 0, lphc );
- }
- return 0;
+ SetWindowLongPtrW( lphc->self, 0, 0 );
+ HeapFree( GetProcessHeap(), 0, lphc );
+ }
+ return 0;
}
/***********************************************************************
DrawFrameControl(hdc, &rectButton, DFC_SCROLL, buttonState);
}
+/***********************************************************************
+ * COMBO_PrepareColors
+ *
+ * This method will sent the appropriate WM_CTLCOLOR message to
+ * prepare and setup the colors for the combo's DC.
+ *
+ * It also returns the brush to use for the background.
+ */
+static HBRUSH COMBO_PrepareColors(
+ LPHEADCOMBO lphc,
+ HDC hDC)
+{
+ HBRUSH hBkgBrush;
+
+ /*
+ * Get the background brush for this control.
+ */
+ if (CB_DISABLED(lphc))
+ {
+#ifdef __REACTOS__
+ hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLORSTATIC);
+#else
+ hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLORSTATIC,
+ (WPARAM)hDC, (LPARAM)lphc->self );
+#endif
+ /*
+ * We have to change the text color since WM_CTLCOLORSTATIC will
+ * set it to the "enabled" color. This is the same behavior as the
+ * edit control
+ */
+ SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT));
+ }
+ else
+ {
+ /* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
+#ifdef __REACTOS__
+ hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLOREDIT);
+#else
+ hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLOREDIT,
+ (WPARAM)hDC, (LPARAM)lphc->self );
+#endif
+ }
+
+ /*
+ * Catch errors.
+ */
+ if( !hBkgBrush )
+ hBkgBrush = GetSysColorBrush(COLOR_WINDOW);
+
+ return hBkgBrush;
+}
+
/***********************************************************************
* CBPaintText
*
*/
static void CBPaintText(
LPHEADCOMBO lphc,
- HDC hdc,
- RECT rectEdit)
+ HDC hdc_paint)
{
+ RECT rectEdit = lphc->textRect;
INT id, size = 0;
LPWSTR pText = NULL;
- if( lphc->wState & CBF_NOREDRAW ) return;
-
TRACE("\n");
/* follow Windows combobox that sends a bunch of text
pText[size] = '\0'; /* just in case */
} else return;
}
- else
- if( !CB_OWNERDRAWN(lphc) )
- return;
if( lphc->wState & CBF_EDIT )
{
static const WCHAR empty_stringW[] = { 0 };
if( CB_HASSTRINGS(lphc) ) SetWindowTextW( lphc->hWndEdit, pText ? pText : empty_stringW );
if( lphc->wState & CBF_FOCUSED )
- SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
+ SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, MAXLONG);
}
- else /* paint text field ourselves */
+ else if(!(lphc->wState & CBF_NOREDRAW) && IsWindowVisible( lphc->self ))
{
- UINT itemState = ODS_COMBOBOXEDIT;
- HFONT hPrevFont = (lphc->hFont) ? SelectObject(hdc, lphc->hFont) : 0;
+ /* paint text field ourselves */
+ HDC hdc = hdc_paint ? hdc_paint : GetDC(lphc->self);
+ UINT itemState = ODS_COMBOBOXEDIT;
+ HFONT hPrevFont = (lphc->hFont) ? SelectObject(hdc, lphc->hFont) : 0;
+ HBRUSH hPrevBrush, hBkgBrush;
/*
* Give ourselves some space.
*/
InflateRect( &rectEdit, -1, -1 );
+ hBkgBrush = COMBO_PrepareColors( lphc, hdc );
+ hPrevBrush = SelectObject( hdc, hBkgBrush );
+ FillRect( hdc, &rectEdit, hBkgBrush );
+
if( CB_OWNERDRAWN(lphc) )
{
DRAWITEMSTRUCT dis;
dis.itemState = itemState;
dis.hDC = hdc;
dis.rcItem = rectEdit;
- dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, id, 0 );
+ dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, id, 0);
/*
* Clip the DC and have the parent draw the item.
SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
- SelectClipRgn( hdc, clipRegion);
+ SelectClipRgn( hdc, clipRegion );
if (clipRegion) DeleteObject( clipRegion );
}
else
&rectEdit,
pText ? pText : empty_stringW , size, NULL );
- if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED) &&
+#ifdef __REACTOS__
+ if(lphc->wState & CBF_FOCUSED &&
+ !(lphc->wState & CBF_DROPPED) &&
!(lphc->UIState & UISF_HIDEFOCUS))
+#else
+ if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED))
+#endif
DrawFocusRect( hdc, &rectEdit );
}
if( hPrevFont )
SelectObject(hdc, hPrevFont );
+
+ if( hPrevBrush )
+ SelectObject( hdc, hPrevBrush );
+
+ if( !hdc_paint )
+ ReleaseDC( lphc->self, hdc );
}
+#ifdef __REACTOS__
if (pText)
+#endif
HeapFree( GetProcessHeap(), 0, pText );
}
DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_RECT);
}
-/***********************************************************************
- * COMBO_PrepareColors
- *
- * This method will sent the appropriate WM_CTLCOLOR message to
- * prepare and setup the colors for the combo's DC.
- *
- * It also returns the brush to use for the background.
- */
-static HBRUSH COMBO_PrepareColors(
- LPHEADCOMBO lphc,
- HDC hDC)
-{
- HBRUSH hBkgBrush;
-
- /*
- * Get the background brush for this control.
- */
- if (CB_DISABLED(lphc))
- {
- hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLORSTATIC);
- /*
- * We have to change the text color since WM_CTLCOLORSTATIC will
- * set it to the "enabled" color. This is the same behavior as the
- * edit control
- */
- SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT));
- }
- else
- {
- /* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
- hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLOREDIT);
- }
-
- /*
- * Catch errors.
- */
- if( !hBkgBrush )
- hBkgBrush = GetSysColorBrush(COLOR_WINDOW);
-
- return hBkgBrush;
-}
-
-
/***********************************************************************
* COMBO_Paint
*/
static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC)
{
PAINTSTRUCT ps;
- HDC hDC;
+ HDC hDC;
- hDC = (hParamDC) ? hParamDC
- : BeginPaint( lphc->self, &ps);
+ hDC = (hParamDC) ? hParamDC : BeginPaint(lphc->self, &ps);
TRACE("hdc=%p\n", hDC);
if( hDC && !(lphc->wState & CBF_NOREDRAW) )
{
- HBRUSH hPrevBrush, hBkgBrush;
+ HBRUSH hPrevBrush, hBkgBrush;
/*
* Retrieve the background brush and select it in the
* DC.
*/
hBkgBrush = COMBO_PrepareColors(lphc, hDC);
-
- hPrevBrush = SelectObject( hDC, hBkgBrush );
+ hPrevBrush = SelectObject(hDC, hBkgBrush);
if (!(lphc->wState & CBF_EDIT))
FillRect(hDC, &lphc->textRect, hBkgBrush);
*/
CBPaintBorder(lphc->self, lphc, hDC);
- if( !IsRectEmpty(&lphc->buttonRect) )
- {
- CBPaintButton(lphc, hDC, lphc->buttonRect);
- }
+ if (!IsRectEmpty(&lphc->buttonRect))
+ CBPaintButton(lphc, hDC, lphc->buttonRect);
/* paint the edit control padding area */
if (CB_GETTYPE(lphc) != CBS_DROPDOWNLIST)
InflateRect(&rPadEdit, EDIT_CONTROL_PADDING(), EDIT_CONTROL_PADDING());
- FrameRect( hDC, &rPadEdit, GetSysColorBrush(COLOR_WINDOW) );
+ FrameRect(hDC, &rPadEdit, GetSysColorBrush(COLOR_WINDOW));
}
- if( !(lphc->wState & CBF_EDIT) )
- CBPaintText( lphc, hDC, lphc->textRect);
+ if (!(lphc->wState & CBF_EDIT))
+ CBPaintText( lphc, hDC );
- if( hPrevBrush )
- SelectObject( hDC, hPrevBrush );
+ if (hPrevBrush)
+ SelectObject( hDC, hPrevBrush );
}
if( !hParamDC )
idx = LB_ERR;
length = SendMessageW( lphc->hWndEdit, WM_GETTEXTLENGTH, 0, 0 );
- if( length > 0 )
+ if (length > 0)
pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR));
TRACE("\t edit text length %i\n", length );
if( pText )
{
GetWindowTextW( lphc->hWndEdit, pText, length + 1);
- idx = SendMessageW(lphc->hWndLBox, LB_FINDSTRING,
- (WPARAM)(-1), (LPARAM)pText );
+ idx = SendMessageW(lphc->hWndLBox, LB_FINDSTRING, (WPARAM)(-1), (LPARAM)pText);
HeapFree( GetProcessHeap(), 0, pText );
}
length = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, (WPARAM)index, 0);
if( length != LB_ERR)
{
- if( (pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR))) )
- {
- SendMessageW(lphc->hWndLBox, LB_GETTEXT,
- (WPARAM)index, (LPARAM)pText );
- }
+ if ((pText = HeapAlloc(GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR))))
+ SendMessageW(lphc->hWndLBox, LB_GETTEXT, (WPARAM)index, (LPARAM)pText );
}
}
lphc->droppedIndex = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX,
- (WPARAM)(lphc->droppedIndex == LB_ERR ? 0 : lphc->droppedIndex), 0 );
+ (WPARAM)(lphc->droppedIndex == LB_ERR ? 0 : lphc->droppedIndex), 0);
SendMessageW(lphc->hWndLBox, LB_CARETON, 0, 0);
}
if (nHeight < nDroppedHeight - COMBO_YBORDERSIZE())
nDroppedHeight = nHeight + COMBO_YBORDERSIZE();
-
- if (nDroppedHeight < nHeight)
- {
- if (nItems < 5)
- nDroppedHeight = (nItems+1)*nIHeight;
- else if (nDroppedHeight < 6*nIHeight)
- nDroppedHeight = 6*nIHeight;
- }
}
+ r.left = rect.left;
+ r.top = rect.bottom;
+ r.right = r.left + lphc->droppedRect.right - lphc->droppedRect.left;
+ r.bottom = r.top + nDroppedHeight;
+
/*If height of dropped rectangle gets beyond a screen size it should go up, otherwise down.*/
monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
mon_info.cbSize = sizeof(mon_info);
GetMonitorInfoW( monitor, &mon_info );
- if( (rect.bottom + nDroppedHeight) >= mon_info.rcWork.bottom )
- rect.bottom = rect.top - nDroppedHeight;
+ if (r.bottom > mon_info.rcWork.bottom)
+ {
+ r.top = max( rect.top - nDroppedHeight, mon_info.rcWork.top );
+ r.bottom = min( r.top + nDroppedHeight, mon_info.rcWork.bottom );
+ }
- SetWindowPos( lphc->hWndLBox, HWND_TOPMOST, rect.left, rect.bottom,
- lphc->droppedRect.right - lphc->droppedRect.left,
- nDroppedHeight,
- SWP_NOACTIVATE | SWP_SHOWWINDOW);
+ SetWindowPos( lphc->hWndLBox, HWND_TOPMOST, r.left, r.top, r.right - r.left, r.bottom - r.top,
+ SWP_NOACTIVATE | SWP_SHOWWINDOW );
if( !(lphc->wState & CBF_NOREDRAW) )
- RedrawWindow( lphc->self, NULL, 0, RDW_INVALIDATE |
- RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+ RedrawWindow( lphc->self, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
EnableWindow( lphc->hWndLBox, TRUE );
if (GetCapture() != lphc->self)
if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
SendMessageW(lphc->hWndLBox, LB_CARETOFF, 0, 0);
- lphc->wState &= ~CBF_FOCUSED;
+ lphc->wState &= ~CBF_FOCUSED;
/* redraw text */
if( !(lphc->wState & CBF_EDIT) )
lphc->wState |= CBF_NOLBSELECT;
CBUpdateEdit( lphc, index );
/* select text in edit, as Windows does */
- SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
+ SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
}
else
{
/***********************************************************************
* COMBO_Size
*/
-static void COMBO_Size( LPHEADCOMBO lphc, LPARAM lParam )
+static void COMBO_Size( LPHEADCOMBO lphc )
{
/*
* Those controls are always the same height. So we have to make sure
*/
if( CB_GETTYPE(lphc) != CBS_SIMPLE )
{
- int newComboHeight;
+ int newComboHeight, curComboHeight, curComboWidth;
+ RECT rc;
+ GetWindowRect(lphc->self, &rc);
+ curComboHeight = rc.bottom - rc.top;
+ curComboWidth = rc.right - rc.left;
newComboHeight = CBGetTextAreaHeight(lphc->self, lphc) + 2*COMBO_YBORDERSIZE();
/*
* the actual control, for example, to do the layout of a dialog that is
* resized, the height of the dropdown is not changed.
*/
- if( HIWORD(lParam) > newComboHeight )
+ if( curComboHeight > newComboHeight )
{
TRACE("oldComboHeight=%d, newComboHeight=%d, oldDropBottom=%d, oldDropTop=%d\n",
- HIWORD(lParam), newComboHeight, lphc->droppedRect.bottom,
+ curComboHeight, newComboHeight, lphc->droppedRect.bottom,
lphc->droppedRect.top);
- lphc->droppedRect.bottom = lphc->droppedRect.top + HIWORD(lParam) - newComboHeight;
+ lphc->droppedRect.bottom = lphc->droppedRect.top + curComboHeight - newComboHeight;
}
/*
* Restore original height
*/
- if( HIWORD(lParam) != newComboHeight )
- SetWindowPos(lphc->self, 0, 0, 0, LOWORD(lParam), newComboHeight,
+ if( curComboHeight != newComboHeight )
+ SetWindowPos(lphc->self, 0, 0, 0, curComboWidth, newComboHeight,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW);
}
&lphc->buttonRect,
&lphc->droppedRect);
- CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, TRUE );
+ CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, FALSE );
}
}
}
else if ( CB_OWNERDRAWN(lphc) ) /* set listbox item height */
- lRet = SendMessageW(lphc->hWndLBox, LB_SETITEMHEIGHT,
- (WPARAM)index, (LPARAM)height );
+ lRet = SendMessageW(lphc->hWndLBox, LB_SETITEMHEIGHT, (WPARAM)index, (LPARAM)height);
return lRet;
}
len = strlen(str);
ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
+#ifdef __REACTOS__
if (ret != NULL)
+#endif
memcpy(ret, str, len + 1);
return ret;
}
/***********************************************************************
* ComboWndProc_common
*/
-LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam, BOOL unicode )
+LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL unicode )
{
- LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
+ LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
#ifdef __REACTOS__
- PWND pWnd;
+ PWND pWnd;
- pWnd = ValidateHwnd(hwnd);
- if (pWnd)
- {
- if (!pWnd->fnid)
- {
+ pWnd = ValidateHwnd(hwnd);
+ if (pWnd)
+ {
+ if (!pWnd->fnid)
+ {
NtUserSetWindowFNID(hwnd, FNID_COMBOBOX);
- }
- else
- {
+ }
+ else
+ {
if (pWnd->fnid != FNID_COMBOBOX)
{
- ERR("Wrong window class for ComboBox! fnId 0x%x\n",pWnd->fnid);
- return 0;
+ ERR("Wrong window class for ComboBox! fnId 0x%x\n",pWnd->fnid);
+ return 0;
}
}
- }
-#endif
+ }
+#endif
- TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
- hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
+ TRACE("[%p]: msg %s wp %08lx lp %08lx\n", hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam);
- if( lphc || message == WM_NCCREATE )
- switch(message)
- {
+#ifndef __REACTOS__
+ if (!IsWindow(hwnd)) return 0;
+#endif
- /* System messages */
+ if (lphc || message == WM_NCCREATE)
+ switch(message)
+ {
+ case WM_NCCREATE:
+ {
+ LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style : ((LPCREATESTRUCTA)lParam)->style;
+ return COMBO_NCCreate(hwnd, style);
+ }
+ case WM_NCDESTROY:
+ COMBO_NCDestroy(lphc);
+#ifdef __REACTOS__
+ NtUserSetWindowFNID(hwnd, FNID_DESTROY);
+#endif
+ break;/* -> DefWindowProc */
- case WM_NCCREATE:
- {
- LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style :
- ((LPCREATESTRUCTA)lParam)->style;
- return COMBO_NCCreate(hwnd, style);
- }
- case WM_NCDESTROY:
- COMBO_NCDestroy(lphc);
+ 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_SIZE:
+ if (lphc->hWndLBox && !(lphc->wState & CBF_NORESIZE))
+ COMBO_Size( lphc );
+ 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 );
+ /* The first time focus is received, select all the text */
+ if (!(lphc->wState & CBF_BEENFOCUSED))
+ {
+ SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
+ lphc->wState |= CBF_BEENFOCUSED;
+ }
+ }
+ else
+ COMBO_SetFocus( lphc );
+ return TRUE;
+ case WM_KILLFOCUS:
+ {
+ HWND hwndFocus = WIN_GetFullHandle((HWND)wParam);
+ if (!hwndFocus || (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox))
+ COMBO_KillFocus( lphc );
+ return TRUE;
+ }
+ case WM_COMMAND:
+ return COMBO_Command( lphc, wParam, WIN_GetFullHandle((HWND)lParam) );
+ 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:
#ifdef __REACTOS__
- NtUserSetWindowFNID(hwnd, FNID_DESTROY);
+ if ( KF_ALTDOWN & HIWORD(lParam) )
+#else
+ if ( KEYDATA_ALT & HIWORD(lParam) )
+#endif
+ if( wParam == VK_UP || wParam == VK_DOWN )
+#ifdef __REACTOS__
+ {
+#endif
+ COMBO_FlipListbox( lphc, FALSE, FALSE );
+ return 0;
+#ifdef __REACTOS__
+ }
+ break;
#endif
- 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_KEYDOWN:
+ 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;
+ }
+ /* fall through */
+ case WM_CHAR:
+ case WM_IME_CHAR:
+ {
+ HWND hwndTarget;
- case WM_PRINTCLIENT:
- /* Fallthrough */
- case WM_PAINT:
- /* wParam may contain a valid HDC! */
- return COMBO_Paint(lphc, (HDC)wParam);
+#ifdef __REACTOS__
+ if (lphc->wState & CBF_DROPPED)
+ lphc->wState |= CBF_NOROLLUP;
+#endif
+ if ( lphc->wState & CBF_EDIT )
+ hwndTarget = lphc->hWndEdit;
+ else
+ hwndTarget = lphc->hWndLBox;
- case WM_ERASEBKGND:
- /* do all painting in WM_PAINT like Windows does */
- return 1;
+ 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;
- case WM_GETDLGCODE:
- {
- LRESULT result = DLGC_WANTARROWS | DLGC_WANTCHARS;
- if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
- {
- int vk = (int)((LPMSG)lParam)->wParam;
+ case WM_CTLCOLOR:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+#ifdef __REACTOS__
+ if (pWnd && !(pWnd->state2 & WNDS2_WIN40COMPAT)) break; // Must be Win 4.0 and above.
+#endif
+ if (lphc->owner)
+ return SendMessageW(lphc->owner, message, wParam, lParam);
+ break;
- if ((vk == VK_RETURN || vk == VK_ESCAPE) && (lphc->wState & CBF_DROPPED))
- result |= DLGC_WANTMESSAGE;
- }
- return result;
- }
- case WM_SIZE:
- if( lphc->hWndLBox &&
- !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc, lParam );
- 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 );
- /* The first time focus is received, select all the text */
- if( !(lphc->wState & CBF_BEENFOCUSED) ) {
- SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
- lphc->wState |= CBF_BEENFOCUSED;
- }
- }
- else
- COMBO_SetFocus( lphc );
- return TRUE;
- case WM_KILLFOCUS:
+ /* Combo messages */
+ 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)
{
- HWND hwndFocus = WIN_GetFullHandle( (HWND)wParam );
- if( !hwndFocus ||
- (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
- COMBO_KillFocus( lphc );
- return TRUE;
+ string = strdupA((LPSTR)lParam);
+ CharLowerA(string);
}
- case WM_COMMAND:
- return COMBO_Command( lphc, wParam, WIN_GetFullHandle( (HWND)lParam ) );
- 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( KF_ALTDOWN & HIWORD(lParam) ) // ReactOS (wine) KEYDATA_ALT
- if( wParam == VK_UP || wParam == VK_DOWN )
- COMBO_FlipListbox( lphc, FALSE, FALSE );
- return 0;
-
- case WM_KEYDOWN:
- 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;
- }
- /* fall through */
- case WM_CHAR:
- case WM_IME_CHAR:
- {
- HWND hwndTarget;
- 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 */
-
- 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;
- }
- 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);
+ else if (lphc->dwStyle & CBS_UPPERCASE)
+ {
+ string = strdupA((LPSTR)lParam);
+ CharUpperA(string);
+ }
- return SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
- }
- case CB_DELETESTRING:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
- SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
- case CB_SELECTSTRING:
- return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
- case CB_FINDSTRING:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
- case CB_FINDSTRINGEXACT:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam);
- case CB_SETITEMHEIGHT:
- return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
- case CB_GETITEMHEIGHT:
- if( (INT)wParam >= 0 ) /* listbox item */
- return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
- return CBGetTextAreaHeight(hwnd, lphc);
- case CB_RESETCONTENT:
- SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
- if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) )
- {
- static const WCHAR empty_stringW[] = { 0 };
- SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)empty_stringW);
- }
- else
- InvalidateRect(lphc->self, NULL, TRUE);
- return TRUE;
- case CB_INITSTORAGE:
- return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam);
- case CB_GETHORIZONTALEXTENT:
- return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
- case CB_SETHORIZONTALEXTENT:
- return SendMessageW(lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0);
- case CB_GETTOPINDEX:
- return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
- case CB_GETLOCALE:
- return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
- case CB_SETLOCALE:
- return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
- case CB_SETDROPPEDWIDTH:
- if( (CB_GETTYPE(lphc) == CBS_SIMPLE) ||
- (INT)wParam >= 32768 )
- return CB_ERR;
- /* new value must be higher than combobox width */
- if((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
- lphc->droppedWidth = wParam;
- else if(wParam)
- lphc->droppedWidth = 0;
-
- /* recalculate the combobox area */
- CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
-
- /* fall through */
- case CB_GETDROPPEDWIDTH:
- if( lphc->droppedWidth )
- return lphc->droppedWidth;
- return lphc->droppedRect.right - lphc->droppedRect.left;
- case CB_GETDROPPEDCONTROLRECT:
- if( lParam ) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
- return CB_OKAY;
- case CB_GETDROPPEDSTATE:
- return (lphc->wState & CBF_DROPPED) ? TRUE : FALSE;
- case CB_DIR:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_DIR, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_DIR, wParam, lParam);
-
- case CB_SHOWDROPDOWN:
- if( CB_GETTYPE(lphc) != CBS_SIMPLE )
- {
- if( wParam )
- {
- if( !(lphc->wState & CBF_DROPPED) )
- CBDropDown( lphc );
- }
- else
- if( lphc->wState & CBF_DROPPED )
- CBRollUp( lphc, FALSE, TRUE );
- }
- return TRUE;
- case CB_GETCOUNT:
- return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
- case CB_GETCURSEL:
- return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
- case CB_SETCURSEL:
- lParam = SendMessageW(lphc->hWndLBox, LB_SETCURSEL, wParam, 0);
- if( lParam >= 0 )
- SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0);
-
- /* no LBN_SELCHANGE in this case, update manually */
- if( lphc->wState & CBF_EDIT )
- CBUpdateEdit( lphc, (INT)wParam );
- else
- InvalidateRect(lphc->self, &lphc->textRect, TRUE);
- lphc->wState &= ~CBF_SELCHANGE;
- return lParam;
- case CB_GETLBTEXT:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_GETTEXT, wParam, lParam);
- case CB_GETLBTEXTLEN:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0) :
- SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0);
- case CB_GETITEMDATA:
- return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
- case CB_SETITEMDATA:
- return SendMessageW(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam);
- case CB_GETEDITSEL:
- /* Edit checks passed parameters itself */
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam);
- return CB_ERR;
- case CB_SETEDITSEL:
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_SETSEL,
- (INT)(INT16)LOWORD(lParam), (INT)(INT16)HIWORD(lParam) );
- return CB_ERR;
- case CB_SETEXTENDEDUI:
- if( CB_GETTYPE(lphc) == CBS_SIMPLE )
- return CB_ERR;
- if( wParam )
- lphc->wState |= CBF_EUI;
- else lphc->wState &= ~CBF_EUI;
- return CB_OKAY;
- case CB_GETEXTENDEDUI:
- return (lphc->wState & CBF_EUI) ? TRUE : FALSE;
- case CB_GETCOMBOBOXINFO:
- return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
- case CB_LIMITTEXT:
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
- return TRUE;
+ ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
+ HeapFree(GetProcessHeap(), 0, string);
+ return ret;
+ }
+ 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);
+ }
+ case CB_DELETESTRING:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
+ SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
+ case CB_SELECTSTRING:
+ return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
+ case CB_FINDSTRING:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
+ case CB_FINDSTRINGEXACT:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam);
+ case CB_SETITEMHEIGHT:
+ return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
+ case CB_GETITEMHEIGHT:
+ if ((INT)wParam >= 0) /* listbox item */
+ return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
+ return CBGetTextAreaHeight(hwnd, lphc);
+ case CB_RESETCONTENT:
+ SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
+ if ((lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc))
+ {
+ static const WCHAR empty_stringW[] = { 0 };
+ SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)empty_stringW);
+ }
+ else
+ InvalidateRect(lphc->self, NULL, TRUE);
+ return TRUE;
+ case CB_INITSTORAGE:
+ return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam);
+ case CB_GETHORIZONTALEXTENT:
+ return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
+ case CB_SETHORIZONTALEXTENT:
+ return SendMessageW(lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0);
+ case CB_GETTOPINDEX:
+ return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
+ case CB_GETLOCALE:
+ return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
+ case CB_SETLOCALE:
+ return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
+ case CB_SETDROPPEDWIDTH:
+ if ((CB_GETTYPE(lphc) == CBS_SIMPLE) || (INT)wParam >= 32768)
+ return CB_ERR;
+ /* new value must be higher than combobox width */
+ if ((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
+ lphc->droppedWidth = wParam;
+ else if (wParam)
+ lphc->droppedWidth = 0;
+
+ /* recalculate the combobox area */
+ CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
+
+ /* fall through */
+ case CB_GETDROPPEDWIDTH:
+ if (lphc->droppedWidth)
+ return lphc->droppedWidth;
+ return lphc->droppedRect.right - lphc->droppedRect.left;
+ case CB_GETDROPPEDCONTROLRECT:
+ if (lParam) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
+ return CB_OKAY;
+ case CB_GETDROPPEDSTATE:
+ return (lphc->wState & CBF_DROPPED) != 0;
+ case CB_DIR:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_DIR, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_DIR, wParam, lParam);
+
+ case CB_SHOWDROPDOWN:
+ if (CB_GETTYPE(lphc) != CBS_SIMPLE)
+ {
+ if (wParam)
+ {
+ if (!(lphc->wState & CBF_DROPPED))
+ CBDropDown( lphc );
+ }
+ else if (lphc->wState & CBF_DROPPED)
+ CBRollUp( lphc, FALSE, TRUE );
+ }
+ return TRUE;
+ case CB_GETCOUNT:
+ return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
+ case CB_GETCURSEL:
+ return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+ case CB_SETCURSEL:
+ lParam = SendMessageW(lphc->hWndLBox, LB_SETCURSEL, wParam, 0);
+ if (lParam >= 0)
+ SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0);
+
+ /* no LBN_SELCHANGE in this case, update manually */
+ CBPaintText(lphc, NULL);
+ lphc->wState &= ~CBF_SELCHANGE;
+ return lParam;
+ case CB_GETLBTEXT:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_GETTEXT, wParam, lParam);
+ case CB_GETLBTEXTLEN:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0) :
+ SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0);
+ case CB_GETITEMDATA:
+ return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
+ case CB_SETITEMDATA:
+ return SendMessageW(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam);
+ case CB_GETEDITSEL:
+ /* Edit checks passed parameters itself */
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam);
+ return CB_ERR;
+ case CB_SETEDITSEL:
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_SETSEL, (INT)(INT16)LOWORD(lParam), (INT)(INT16)HIWORD(lParam) );
+ return CB_ERR;
+ case CB_SETEXTENDEDUI:
+ if (CB_GETTYPE(lphc) == CBS_SIMPLE )
+ return CB_ERR;
+ if (wParam)
+ lphc->wState |= CBF_EUI;
+ else lphc->wState &= ~CBF_EUI;
+ return CB_OKAY;
+ case CB_GETEXTENDEDUI:
+ return (lphc->wState & CBF_EUI) != 0;
+ case CB_GETCOMBOBOXINFO:
+ return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
+ case CB_LIMITTEXT:
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
+ return TRUE;
+#ifdef __REACTOS__
case WM_UPDATEUISTATE:
if (unicode)
DefWindowProcW(lphc->self, message, wParam, lParam);
if (COMBO_update_uistate(lphc))
{
/* redraw text */
- if( !(lphc->wState & CBF_EDIT) )
+ if (!(lphc->wState & CBF_EDIT))
NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE);
}
break;
- default:
- if (message >= WM_USER)
- WARN("unknown msg WM_USER+%04x wp=%04lx lp=%08lx\n",
- message - WM_USER, wParam, lParam );
- break;
- }
- return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
- DefWindowProcA(hwnd, message, wParam, lParam);
+ case WM_CBLOSTTEXTFOCUS: /* undocumented message - deselects the text when focus is lost */
+ if (lphc->hWndEdit != NULL)
+ {
+ SendMessage(lphc->self, WM_LBUTTONUP, 0, 0xFFFFFFFF);
+ SendMessage(lphc->hWndEdit, EM_SETSEL, 0, 0);
+ lphc->wState &= ~(CBF_FOCUSED | CBF_BEENFOCUSED);
+ CB_NOTIFY(lphc, CBN_KILLFOCUS);
+ }
+ return TRUE;
+#endif
+
+ default:
+ if (message >= WM_USER)
+ WARN("unknown msg WM_USER+%04x wp=%04lx lp=%08lx\n", message - WM_USER, wParam, lParam );
+ break;
+ }
+ return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
+ DefWindowProcA(hwnd, message, wParam, lParam);
}
+#ifdef __REACTOS__
+
/***********************************************************************
* ComboWndProcA
*
* This is just a wrapper for the real ComboWndProc which locks/unlocks
* window structs.
*/
-LRESULT WINAPI ComboWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+LRESULT WINAPI ComboWndProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!IsWindow(hwnd)) return 0;
- return ComboWndProc_common( hwnd, message, wParam, lParam, FALSE );
+ return ComboWndProc_common(hwnd, message, wParam, lParam, FALSE);
}
/***********************************************************************
* ComboWndProcW
*/
-LRESULT WINAPI ComboWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+LRESULT WINAPI ComboWndProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!IsWindow(hwnd)) return 0;
- return ComboWndProc_common( hwnd, message, wParam, lParam, TRUE );
+ return ComboWndProc_common(hwnd, message, wParam, lParam, TRUE);
}
+#endif /* __REACTOS__ */
+
/*************************************************************************
* GetComboBoxInfo (USER32.@)
*/
-BOOL WINAPI GetComboBoxInfo(HWND hwndCombo, /* [in] handle to combo box */
- PCOMBOBOXINFO pcbi /* [in/out] combo box information */)
+BOOL WINAPI GetComboBoxInfo(
+ HWND hwndCombo, /* [in] handle to combo box */
+ PCOMBOBOXINFO pcbi /* [in/out] combo box information */)
{
TRACE("(%p, %p)\n", hwndCombo, pcbi);
-#ifndef __REACTOS__
- return SendMessageW(hwndCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi);
-#else
+#ifdef __REACTOS__
return NtUserGetComboBoxInfo(hwndCombo, pcbi);
+#else
+ return SendMessageW(hwndCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi);
#endif
}