* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * FIXME: roll up in Netscape 3.01.
+ * 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 <stdarg.h>
-#include <string.h>
-
+#include <user32.h>
#define NDEBUG
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "controls.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
+#include <debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(combo);
#define CB_NOTIFY( lphc, code ) \
(SendMessageW((lphc)->owner, WM_COMMAND, \
- MAKEWPARAM(GetWindowLongA((lphc)->self,GWL_ID), (code)), (LPARAM)(lphc)->self))
+ MAKEWPARAM(GetWindowLongPtrW((lphc)->self,GWLP_ID), (code)), (LPARAM)(lphc)->self))
#define CB_DISABLED( lphc ) (!IsWindowEnabled((lphc)->self))
#define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
if (COMBO_Init() && (lphc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEADCOMBO))) )
{
lphc->self = hwnd;
- SetWindowLongA( hwnd, 0, (LONG)lphc );
+ SetWindowLongW( hwnd, 0, (LONG)lphc );
/* some braindead apps do try to use scrollbar/border flags */
lphc->dwStyle = style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
- SetWindowLongA( hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL) );
+ SetWindowLongW( hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL) );
/*
* We also have to remove the client edge style to make sure
* we don't end-up with a non client area.
*/
- SetWindowLongA( hwnd, GWL_EXSTYLE,
- GetWindowLongA( hwnd, GWL_EXSTYLE ) & ~WS_EX_CLIENTEDGE );
+ SetWindowLongW( hwnd, GWL_EXSTYLE,
+ GetWindowLongW( hwnd, GWL_EXSTYLE ) & ~WS_EX_CLIENTEDGE );
if( !(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
lphc->dwStyle |= CBS_HASSTRINGS;
- if( !(GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) )
+ if( !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) )
lphc->wState |= CBF_NOTIFY;
TRACE("[%p], style = %08x\n", lphc, lphc->dwStyle );
if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
DestroyWindow( lphc->hWndLBox );
- SetWindowLongA( lphc->self, 0, 0 );
+ SetWindowLongPtrW( lphc->self, 0, 0 );
HeapFree( GetProcessHeap(), 0, lphc );
}
return 0;
MEASUREITEMSTRUCT measureItem;
RECT clientRect;
INT originalItemHeight = iTextItemHeight;
- UINT id = GetWindowLongA( lphc->self, GWL_ID );
+ UINT id = GetWindowLongPtrW( lphc->self, GWLP_ID );
/*
* We use the client rect for the width of the item.
if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
lphc->droppedRect.left += COMBO_EDITBUTTONSPACE();
- ClientToScreen(hwnd, (LPPOINT)&lphc->droppedRect);
- ClientToScreen(hwnd, (LPPOINT)&lphc->droppedRect.right);
+ if (lphc->droppedRect.bottom < lphc->droppedRect.top)
+ lphc->droppedRect.bottom = lphc->droppedRect.top;
+ if (lphc->droppedRect.right < lphc->droppedRect.left)
+ lphc->droppedRect.right = lphc->droppedRect.left;
+ MapWindowPoints( hwnd, 0, (LPPOINT)&lphc->droppedRect, 2 );
}
/* create listbox popup */
- lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS | WS_CHILD) |
+ lbeStyle = (LBS_NOTIFY | LBS_COMBOBOX | WS_BORDER | WS_CLIPSIBLINGS | WS_CHILD) |
(style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE));
if( lphc->dwStyle & CBS_SORT )
lphc->droppedRect.right - lphc->droppedRect.left,
lphc->droppedRect.bottom - lphc->droppedRect.top,
hwnd, (HMENU)ID_CB_LISTBOX,
- (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), lphc );
+ (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), lphc );
else
lphc->hWndLBox = CreateWindowExA(lbeExStyle, "ComboLBox", NULL, lbeStyle,
lphc->droppedRect.left,
lphc->droppedRect.right - lphc->droppedRect.left,
lphc->droppedRect.bottom - lphc->droppedRect.top,
hwnd, (HMENU)ID_CB_LISTBOX,
- (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), lphc );
+ (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), lphc );
if( lphc->hWndLBox )
{
lphc->textRect.right - lphc->textRect.left,
lphc->textRect.bottom - lphc->textRect.top,
hwnd, (HMENU)ID_CB_EDIT,
- (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), NULL );
+ (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), NULL );
else
lphc->hWndEdit = CreateWindowExA(0, "Edit", NULL, lbeStyle,
lphc->textRect.left, lphc->textRect.top,
lphc->textRect.right - lphc->textRect.left,
lphc->textRect.bottom - lphc->textRect.top,
hwnd, (HMENU)ID_CB_EDIT,
- (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), NULL );
+ (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), NULL );
if( !lphc->hWndEdit )
bEdit = FALSE;
{
DRAWITEMSTRUCT dis;
HRGN clipRegion;
- UINT ctlid = GetWindowLongA( lphc->self, GWL_ID );
+ UINT ctlid = (UINT)GetWindowLongPtrW( lphc->self, GWLP_ID );
/* setup state for DRAWITEM message. Owner will highlight */
if ( (lphc->wState & CBF_FOCUSED) &&
if( lphc->wState & CBF_FOCUSED )
SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
- if( pText )
- HeapFree( GetProcessHeap(), 0, pText );
+ HeapFree( GetProcessHeap(), 0, pText );
}
/***********************************************************************
static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, LPARAM lParam )
{
HWND hWnd = lphc->self;
- UINT id = GetWindowLongA( hWnd, GWL_ID );
+ UINT id = (UINT)GetWindowLongPtrW( hWnd, GWLP_ID );
TRACE("[%p]: ownerdraw op %04x\n", lphc->self, msg );
if (!count || !buf) return 0;
if( lphc->hWndLBox )
{
- INT idx = SendMessageA(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+ INT idx = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
if (idx == LB_ERR) goto error;
length = SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, idx, 0 );
if (length == LB_ERR) goto error;
}
}
+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;
+}
/***********************************************************************
* ComboWndProc_common
static LRESULT ComboWndProc_common( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam, BOOL unicode )
{
- LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongA( hwnd, 0 );
+ LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
- TRACE("[%p]: msg %s wp %08x lp %08lx\n",
- hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
+ //TRACE("[%p]: msg %s wp %08x lp %08lx\n",
+ // hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
if( lphc || message == WM_NCCREATE )
switch(message)
/* fall through */
#endif
case CB_ADDSTRING:
- if( unicode )
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- strlwrW((LPWSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- struprW((LPWSTR)lParam);
- return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
- }
+ {
+ UINT msg = LB_ADDSTRING;
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ msg = LB_ADDSTRING_LOWER;
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ msg = LB_ADDSTRING_UPPER;
+ if( unicode )
+ return SendMessageW(lphc->hWndLBox, msg, 0, lParam);
else
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- _strlwr((LPSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- _strupr((LPSTR)lParam);
- return SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
- }
+ return SendMessageA(lphc->hWndLBox, msg, 0, lParam);
+ }
#ifndef __REACTOS__
case CB_INSERTSTRING16:
wParam = (INT)(INT16)wParam;
/* fall through */
#endif
case CB_INSERTSTRING:
- if( unicode )
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- strlwrW((LPWSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- struprW((LPWSTR)lParam);
- return SendMessageW(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
- }
+ {
+ UINT msg = LB_INSERTSTRING;
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ msg = LB_INSERTSTRING_LOWER;
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ msg = LB_INSERTSTRING_UPPER;
+ if( unicode )
+ return SendMessageW(lphc->hWndLBox, msg, 0, lParam);
else
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- _strlwr((LPSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- _strupr((LPSTR)lParam);
- return SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
- }
+ return SendMessageA(lphc->hWndLBox, msg, 0, lParam);
+ }
#ifndef __REACTOS__
case CB_DELETESTRING16:
#endif
#endif
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);
+ break;
default:
if (message >= WM_USER)
WARN("unknown msg WM_USER+%04x wp=%04x lp=%08lx\n",
BOOL WINAPI GetComboBoxInfo(HWND hwndCombo, /* [in] handle to combo box */
PCOMBOBOXINFO pcbi /* [in/out] combo box information */)
{
- FIXME("\n");
- return FALSE;
-
+ return SendMessageW(hwndCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi);
}