1236 lines
38 KiB
C
1236 lines
38 KiB
C
/*
|
|
* Combo controls
|
|
*
|
|
* Copyright 1993 Martin Ayotte
|
|
* Copyright 1995 Bernd Schmidt
|
|
* Copyright 1996 Albrecht Kleine [some fixes]
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "windows.h"
|
|
#include "sysmetrics.h"
|
|
#include "win.h"
|
|
#include "combo.h"
|
|
#include "user.h"
|
|
#include "graphics.h"
|
|
#include "heap.h"
|
|
#include "listbox.h"
|
|
#include "drive.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
#include "xmalloc.h"
|
|
|
|
/*
|
|
* Note: Combos are probably implemented in a different way by Windows.
|
|
* Using a message spy for Windows, you can see some undocumented
|
|
* messages being passed between ComboBox and ComboLBox.
|
|
* I hope no programs rely on the implementation of combos.
|
|
*/
|
|
|
|
#define ID_EDIT 1
|
|
#define ID_CLB 2
|
|
#define CBLMM_EDGE 4 /* distance inside box which is same as moving mouse
|
|
outside box, to trigger scrolling of CBL */
|
|
|
|
static BOOL CBCheckSize(HWND hwnd);
|
|
static BOOL CBLCheckSize(HWND hwnd);
|
|
|
|
static HBITMAP16 hComboBit = 0;
|
|
static WORD CBitHeight, CBitWidth;
|
|
|
|
static int COMBO_Init()
|
|
{
|
|
BITMAP16 bm;
|
|
|
|
dprintf_combo(stddeb, "COMBO_Init\n");
|
|
hComboBit = LoadBitmap16(0, MAKEINTRESOURCE(OBM_COMBO));
|
|
GetObject16( hComboBit, sizeof(bm), &bm );
|
|
CBitHeight = bm.bmHeight;
|
|
CBitWidth = bm.bmWidth;
|
|
return 0;
|
|
}
|
|
|
|
LPHEADCOMBO ComboGetStorageHeader(HWND hwnd)
|
|
{
|
|
return (LPHEADCOMBO)GetWindowLong32A(hwnd,4);
|
|
}
|
|
|
|
LPHEADLIST ComboGetListHeader(HWND hwnd)
|
|
{
|
|
return (LPHEADLIST)GetWindowLong32A(hwnd,0);
|
|
}
|
|
|
|
int CreateComboStruct(HWND hwnd, LONG style)
|
|
{
|
|
LPHEADCOMBO lphc;
|
|
|
|
lphc = (LPHEADCOMBO)xmalloc(sizeof(HEADCOMBO));
|
|
SetWindowLong32A(hwnd,4,(LONG)lphc);
|
|
lphc->hWndEdit = 0;
|
|
lphc->hWndLBox = 0;
|
|
lphc->dwState = 0;
|
|
lphc->LastSel = -1;
|
|
lphc->dwStyle = style;
|
|
lphc->DropDownVisible = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
void ComboUpdateWindow(HWND hwnd, LPHEADLIST lphl, LPHEADCOMBO lphc, BOOL repaint)
|
|
{
|
|
WND *wndPtr = WIN_FindWndPtr(hwnd);
|
|
|
|
if (wndPtr->dwStyle & WS_VSCROLL)
|
|
SetScrollRange32(lphc->hWndLBox,SB_VERT,0,ListMaxFirstVisible(lphl),TRUE);
|
|
if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBNCCreate
|
|
*/
|
|
static LRESULT CBNCCreate(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
CREATESTRUCT16 *createStruct;
|
|
|
|
if (!hComboBit) COMBO_Init();
|
|
|
|
createStruct = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
|
|
createStruct->style |= WS_BORDER;
|
|
SetWindowLong32A(hwnd, GWL_STYLE, createStruct->style);
|
|
|
|
dprintf_combo(stddeb,"ComboBox WM_NCCREATE!\n");
|
|
return DefWindowProc16(hwnd, WM_NCCREATE, wParam, lParam);
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBCreate
|
|
*/
|
|
static LRESULT CBCreate(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl;
|
|
LPHEADCOMBO lphc;
|
|
LONG style = 0;
|
|
LONG cstyle = GetWindowLong32A(hwnd,GWL_STYLE);
|
|
RECT16 rect,lboxrect;
|
|
WND* wndPtr = WIN_FindWndPtr(hwnd);
|
|
char className[] = "COMBOLBOX"; /* Hack so that class names are > 0x10000 */
|
|
char editName[] = "EDIT";
|
|
HWND hwndp=0;
|
|
|
|
/* translate combo into listbox styles */
|
|
cstyle |= WS_BORDER;
|
|
if (cstyle & CBS_OWNERDRAWFIXED) style |= LBS_OWNERDRAWFIXED;
|
|
if (cstyle & CBS_OWNERDRAWVARIABLE) style |= LBS_OWNERDRAWVARIABLE;
|
|
if (cstyle & CBS_SORT) style |= LBS_SORT;
|
|
if (cstyle & CBS_HASSTRINGS) style |= LBS_HASSTRINGS;
|
|
style |= LBS_NOTIFY;
|
|
CreateListBoxStruct(hwnd, ODT_COMBOBOX, style, GetParent16(hwnd));
|
|
CreateComboStruct(hwnd,cstyle);
|
|
|
|
lphl = ComboGetListHeader(hwnd);
|
|
lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
GetClientRect16(hwnd,&rect);
|
|
lphc->LBoxTop = lphl->StdItemHeight;
|
|
|
|
switch(cstyle & 3)
|
|
{
|
|
case CBS_SIMPLE: /* edit control, list always visible */
|
|
lboxrect=rect;
|
|
dprintf_combo(stddeb,"CBS_SIMPLE\n");
|
|
style= WS_BORDER | WS_CHILD | WS_VISIBLE | WS_VSCROLL;
|
|
SetRectEmpty16(&lphc->RectButton);
|
|
hwndp=hwnd;
|
|
break;
|
|
|
|
case CBS_DROPDOWNLIST: /* static control, dropdown listbox */
|
|
case CBS_DROPDOWN: /* edit control, dropdown listbox */
|
|
GetWindowRect16(hwnd,&lboxrect);
|
|
style = WS_POPUP | WS_BORDER | WS_VSCROLL;
|
|
/* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
|
|
* set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
|
|
* flag doesn't work. */
|
|
lphc->RectButton = rect;
|
|
lphc->RectButton.left = lphc->RectButton.right - 6 - CBitWidth;
|
|
lphc->RectButton.bottom = lphc->RectButton.top + lphl->StdItemHeight;
|
|
SetWindowPos32(hwnd, 0, 0, 0, rect.right -rect.left + 2*SYSMETRICS_CXBORDER,
|
|
lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE);
|
|
dprintf_combo(stddeb,(cstyle & 3)==CBS_DROPDOWN ? "CBS_DROPDOWN\n": "CBS_DROPDOWNLIST\n");
|
|
break;
|
|
|
|
default: fprintf(stderr,"COMBOBOX error: bad class style!\n");
|
|
return 0;
|
|
}
|
|
|
|
if ((cstyle & 3) != CBS_DROPDOWNLIST)
|
|
lphc->hWndEdit = CreateWindow16( editName, NULL,
|
|
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | ES_LEFT,
|
|
0, 0, rect.right-6-CBitWidth,
|
|
lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
|
|
hwnd, (HMENU16)ID_EDIT, WIN_GetWindowInstance(hwnd), NULL );
|
|
|
|
lboxrect.top+=lphc->LBoxTop;
|
|
lphc->hWndLBox = CreateWindow16( className, NULL, style |
|
|
((cstyle & WS_HSCROLL)? WS_HSCROLL : 0) |
|
|
((cstyle & WS_VSCROLL)? WS_VSCROLL : 0),
|
|
lboxrect.left, lboxrect.top,
|
|
lboxrect.right - lboxrect.left,
|
|
lboxrect.bottom - lboxrect.top,
|
|
hwndp,(HMENU16)ID_CLB, WIN_GetWindowInstance(hwnd),
|
|
(LPVOID)(HWND32)hwnd );
|
|
|
|
wndPtr->dwStyle &= ~(WS_VSCROLL | WS_HSCROLL);
|
|
|
|
dprintf_combo( stddeb, "Combo Creation hwnd=%04x LBox=%04x Edit=%04x\n",
|
|
hwnd, lphc->hWndLBox, lphc->hWndEdit);
|
|
dprintf_combo( stddeb, " lbox %d,%d-%d,%d button %d,%d-%d,%d\n",
|
|
lboxrect.left, lboxrect.top, lboxrect.right, lboxrect.bottom,
|
|
lphc->RectButton.left, lphc->RectButton.top,
|
|
lphc->RectButton.right, lphc->RectButton.bottom );
|
|
dprintf_combo( stddeb, " client %d,%d-%d,%d window %d,%d-%d,%d\n",
|
|
wndPtr->rectClient.left, wndPtr->rectClient.top,
|
|
wndPtr->rectClient.right, wndPtr->rectClient.bottom,
|
|
wndPtr->rectWindow.left, wndPtr->rectWindow.top,
|
|
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBDestroy
|
|
*/
|
|
static LRESULT CBDestroy(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
if (lphc->hWndEdit) DestroyWindow32( lphc->hWndEdit );
|
|
if (lphc->hWndLBox) DestroyWindow32( lphc->hWndLBox );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBPaint
|
|
*/
|
|
static LRESULT CBPaint(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
PAINTSTRUCT16 ps;
|
|
HBRUSH32 hBrush;
|
|
HFONT32 hOldFont;
|
|
HDC16 hdc;
|
|
RECT16 rect;
|
|
|
|
hdc = BeginPaint16(hwnd, &ps);
|
|
|
|
GetClientRect16(hwnd, &rect);
|
|
CBCheckSize(hwnd);
|
|
/* 1 for button border */
|
|
rect.right = lphc->RectButton.left - 1;
|
|
|
|
if (hComboBit != 0 && !IsRectEmpty16(&lphc->RectButton))
|
|
{
|
|
Rectangle32(hdc,lphc->RectButton.left-1,lphc->RectButton.top-1,
|
|
lphc->RectButton.right+1,lphc->RectButton.bottom+1);
|
|
{
|
|
RECT32 r;
|
|
CONV_RECT16TO32( &lphc->RectButton, &r );
|
|
GRAPH_DrawReliefRect(hdc, &r, 2, 2, FALSE);
|
|
}
|
|
GRAPH_DrawBitmap(hdc, hComboBit,
|
|
lphc->RectButton.left + 2,lphc->RectButton.top + 2,
|
|
0, 0, CBitWidth, CBitHeight );
|
|
}
|
|
if (!IsWindowVisible16(hwnd) || !lphl->bRedrawFlag
|
|
|| (lphc->dwStyle & 3) != CBS_DROPDOWNLIST)
|
|
{
|
|
/* we don't want to draw an entry when there is an edit control */
|
|
EndPaint16(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
hOldFont = SelectObject32(hdc, lphl->hFont);
|
|
|
|
hBrush = SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX, hdc, hwnd );
|
|
if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH);
|
|
|
|
lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
|
|
if (lpls != NULL) {
|
|
FillRect16(hdc, &rect, hBrush);
|
|
ListBoxDrawItem (hwnd, lphl, hdc, lpls, &rect, ODA_DRAWENTIRE, 0);
|
|
if (GetFocus32() == hwnd)
|
|
ListBoxDrawItem (hwnd,lphl, hdc, lpls, &rect, ODA_FOCUS, ODS_FOCUS);
|
|
}
|
|
else FillRect16(hdc, &rect, hBrush);
|
|
SelectObject32(hdc,hOldFont);
|
|
EndPaint16(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetDlgCode
|
|
*/
|
|
static LRESULT CBGetDlgCode(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
return DLGC_WANTARROWS | DLGC_WANTCHARS;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLButtonDown
|
|
*/
|
|
static LRESULT CBLButtonDown(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
SendMessage16(hwnd,CB_SHOWDROPDOWN16,!lphc->DropDownVisible,0);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBKeyDown
|
|
*/
|
|
static LRESULT CBKeyDown(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
WORD newFocused = lphl->ItemFocused;
|
|
|
|
switch(wParam) {
|
|
case VK_HOME:
|
|
newFocused = 0;
|
|
break;
|
|
case VK_END:
|
|
newFocused = lphl->ItemsCount - 1;
|
|
break;
|
|
case VK_UP:
|
|
if (newFocused > 0) newFocused--;
|
|
break;
|
|
case VK_DOWN:
|
|
newFocused++;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if (newFocused >= lphl->ItemsCount)
|
|
newFocused = lphl->ItemsCount - 1;
|
|
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
SendMessage16(hwnd, WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
|
|
ListBoxSendNotification(lphl, CBN_SELCHANGE);
|
|
|
|
lphl->ItemFocused = newFocused;
|
|
ListBoxScrollToFocus(lphl);
|
|
/* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBChar
|
|
*/
|
|
static LRESULT CBChar(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
WORD newFocused;
|
|
|
|
newFocused = ListBoxFindNextMatch(lphl, wParam);
|
|
if (newFocused == (WORD)LB_ERR) return 0;
|
|
|
|
if (newFocused >= lphl->ItemsCount)
|
|
newFocused = lphl->ItemsCount - 1;
|
|
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
SendMessage16(hwnd, WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
|
|
ListBoxSendNotification(lphl, CBN_SELCHANGE);
|
|
lphl->ItemFocused = newFocused;
|
|
ListBoxScrollToFocus(lphl);
|
|
|
|
/* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBKillFocus
|
|
*/
|
|
static LRESULT CBKillFocus(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetFocus
|
|
*/
|
|
static LRESULT CBSetFocus(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBResetContent
|
|
*/
|
|
static LRESULT CBResetContent(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
ListBoxResetContent(lphl);
|
|
ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBDir
|
|
*/
|
|
static LRESULT CBDir(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
WORD wRet;
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
wRet = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
|
|
ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBInsertString
|
|
*/
|
|
static LRESULT CBInsertString(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
WORD wRet;
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
if (lphl->HasStrings)
|
|
wRet = ListBoxInsertString(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
|
|
else
|
|
wRet = ListBoxInsertString(lphl, wParam, (LPSTR)lParam);
|
|
ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBAddString
|
|
*/
|
|
static LRESULT CBAddString(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
WORD wRet;
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
wRet = ListBoxAddString(lphl, (SEGPTR)lParam);
|
|
|
|
ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBDeleteString
|
|
*/
|
|
static LRESULT CBDeleteString(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
LONG lRet = ListBoxDeleteString(lphl,wParam);
|
|
|
|
ComboUpdateWindow(hwnd, lphl, lphc, TRUE);
|
|
return lRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSelectString
|
|
*/
|
|
static LRESULT CBSelectString(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
WORD wRet;
|
|
|
|
wRet = ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
|
|
|
|
/* XXX add functionality here */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBFindString
|
|
*/
|
|
static LRESULT CBFindString(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxFindString(lphl, wParam, (SEGPTR)lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBFindStringExact
|
|
*/
|
|
static LRESULT CBFindStringExact(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxFindStringExact(lphl, wParam, (SEGPTR)lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetCount
|
|
*/
|
|
static LRESULT CBGetCount(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return lphl->ItemsCount;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetCurSel
|
|
*/
|
|
static LRESULT CBSetCurSel(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
WORD wRet;
|
|
|
|
wRet = ListBoxSetCurSel(lphl, wParam);
|
|
|
|
dprintf_combo(stddeb,"CBSetCurSel: hwnd %04x wp %x lp %lx wRet %d\n",
|
|
hwnd,wParam,lParam,wRet);
|
|
/* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
|
|
return wRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetCurSel
|
|
*/
|
|
static LRESULT CBGetCurSel(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return lphl->ItemFocused;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetItemHeight
|
|
*/
|
|
static LRESULT CBGetItemHeight(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
|
|
|
|
if (lpls == NULL) return LB_ERR;
|
|
return lpls->mis.itemHeight;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetItemHeight
|
|
*/
|
|
static LRESULT CBSetItemHeight(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxSetItemHeight(lphl, wParam, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetRedraw
|
|
*/
|
|
static LRESULT CBSetRedraw(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
lphl->bRedrawFlag = wParam;
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetFont
|
|
*/
|
|
static LRESULT CBSetFont(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
if (wParam == 0)
|
|
lphl->hFont = GetStockObject32(SYSTEM_FONT);
|
|
else
|
|
lphl->hFont = (HFONT16)wParam;
|
|
if (lphc->hWndEdit)
|
|
SendMessage16(lphc->hWndEdit,WM_SETFONT,lphl->hFont,0);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetLBTextLen
|
|
*/
|
|
static LRESULT CBGetLBTextLen(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
|
|
|
|
if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
|
|
return strlen(lpls->itemText);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetLBText
|
|
*/
|
|
static LRESULT CBGetLBText(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetItemData
|
|
*/
|
|
static LRESULT CBGetItemData(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxGetItemData(lphl, wParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBSetItemData
|
|
*/
|
|
static LRESULT CBSetItemData(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
return ListBoxSetItemData(lphl, wParam, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBShowDropDown
|
|
*/
|
|
static LRESULT CBShowDropDown(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
RECT32 rect;
|
|
|
|
if ((lphc->dwStyle & 3) == CBS_SIMPLE) return LB_ERR;
|
|
|
|
wParam = !!wParam;
|
|
if (wParam != lphc->DropDownVisible) {
|
|
lphc->DropDownVisible = wParam;
|
|
GetWindowRect32(hwnd,&rect);
|
|
SetWindowPos32(lphc->hWndLBox, 0, rect.left, rect.top+lphc->LBoxTop, 0, 0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE |
|
|
(wParam ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
|
|
if (!wParam) SetFocus32(hwnd);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CBCheckSize
|
|
*/
|
|
static BOOL CBCheckSize(HWND hwnd)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LONG cstyle = GetWindowLong32A(hwnd,GWL_STYLE);
|
|
RECT16 cRect, wRect;
|
|
|
|
if (lphc->hWndLBox == 0) return FALSE;
|
|
|
|
GetClientRect16(hwnd,&cRect);
|
|
GetWindowRect16(hwnd,&wRect);
|
|
|
|
dprintf_combo(stddeb,
|
|
"CBCheckSize: hwnd %04x Rect %d,%d-%d,%d wRect %d,%d-%d,%d\n",
|
|
hwnd,cRect.left,cRect.top,cRect.right,cRect.bottom,
|
|
wRect.left,wRect.top,wRect.right,wRect.bottom);
|
|
if ((cstyle & 3) == CBS_SIMPLE) return TRUE;
|
|
|
|
if ((cRect.bottom - cRect.top) >
|
|
(lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER)) {
|
|
SetWindowPos32(hwnd, 0, 0, 0,
|
|
cRect.right-cRect.left,
|
|
lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
|
|
GetClientRect16(hwnd,&cRect);
|
|
GetWindowRect16(hwnd,&wRect);
|
|
|
|
lphc->RectButton.right = cRect.right;
|
|
lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4
|
|
- CBitWidth;
|
|
lphc->RectButton.top = cRect.top;
|
|
lphc->RectButton.bottom = cRect.bottom;
|
|
}
|
|
|
|
if (cRect.right < lphc->RectButton.left) {
|
|
/* if the button is outside the window move it in */
|
|
if ((wRect.right - wRect.left - 2*SYSMETRICS_CXBORDER) == (cRect.right - cRect.left)) {
|
|
lphc->RectButton.right = cRect.right;
|
|
lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4
|
|
- CBitWidth;
|
|
lphc->RectButton.top = cRect.top;
|
|
lphc->RectButton.bottom = cRect.bottom;
|
|
}
|
|
/* otherwise we need to make the client include the button */
|
|
else
|
|
SetWindowPos32(hwnd, 0, 0, 0, lphc->RectButton.right,
|
|
lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
|
|
|
|
if ((lphc->dwStyle & 3) != CBS_DROPDOWNLIST)
|
|
SetWindowPos32(lphc->hWndEdit, 0, 0, 0, lphc->RectButton.left,
|
|
lphl->StdItemHeight,
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
|
|
}
|
|
|
|
CBLCheckSize(hwnd);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBCommand
|
|
*/
|
|
static LRESULT CBCommand(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
char buffer[256];
|
|
WORD newFocused;
|
|
WORD id;
|
|
if (lphc->hWndEdit) /* interdependence only used for CBS_SIMPLE and CBS_DROPDOWN styles */
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case ID_CLB: /* update EDIT window */
|
|
if (HIWORD(lParam)==CBN_SELCHANGE)
|
|
if (lphl->HasStrings)
|
|
{
|
|
ListBoxGetText(lphl,lphl->ItemFocused, buffer);
|
|
dprintf_combo(stddeb,"CBCommand: update Edit: %s\n",buffer);
|
|
SetWindowText32A( lphc->hWndEdit, buffer );
|
|
}
|
|
break;
|
|
case ID_EDIT: /* update LISTBOX window */
|
|
id=GetWindowWord(hwnd,GWW_ID);
|
|
switch (HIWORD(lParam))
|
|
{
|
|
case EN_UPDATE:GetWindowText32A(lphc->hWndEdit,buffer,255);
|
|
if (*buffer)
|
|
{
|
|
char *str = SEGPTR_STRDUP(buffer);
|
|
newFocused=ListBoxFindString(lphl, -1, SEGPTR_GET(str));
|
|
SEGPTR_FREE(str);
|
|
dprintf_combo(stddeb,"CBCommand: new selection #%d is= %s\n",
|
|
newFocused,buffer);
|
|
if (newFocused != (WORD)LB_ERR)
|
|
{ /* if found something */
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
ListBoxSendNotification(lphl, CBN_SELCHANGE);
|
|
InvalidateRect32(hwnd, NULL, TRUE);
|
|
}
|
|
}
|
|
SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
|
|
MAKELONG(hwnd, CBN_EDITUPDATE));
|
|
break;
|
|
case EN_CHANGE:SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
|
|
MAKELONG(hwnd, CBN_EDITCHANGE));
|
|
break;
|
|
case EN_ERRSPACE:SendMessage16(GetParent16(hwnd),WM_COMMAND,id,
|
|
MAKELONG(hwnd, CBN_ERRSPACE));
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CBGetEditSel
|
|
* Look out! Under Win32, the parameter packing is very different.
|
|
*/
|
|
static LRESULT CBGetEditSel(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
|
|
return CB_ERR; /* err, documented for CBSetEditSel */
|
|
return SendMessage16(lphc->hWndEdit, EM_GETSEL16, 0, 0);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CBSetEditSel
|
|
* Look out! Under Win32, the parameter packing is very different.
|
|
*/
|
|
static LRESULT CBSetEditSel(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
|
|
return CB_ERR;
|
|
return SendMessage16(lphc->hWndEdit, EM_SETSEL16, 0, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBGetText
|
|
*/
|
|
static LRESULT CBGetText(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
|
|
return SendMessage16(lphc->hWndEdit, WM_GETTEXT, wParam, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ComboWndProc
|
|
*/
|
|
LRESULT ComboBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
switch(message) {
|
|
case WM_NCCREATE: return CBNCCreate(hwnd, wParam, lParam);
|
|
case WM_CREATE: return CBCreate(hwnd, wParam, lParam);
|
|
case WM_DESTROY: return CBDestroy(hwnd, wParam, lParam);
|
|
case WM_GETDLGCODE: return CBGetDlgCode(hwnd, wParam, lParam);
|
|
case WM_KEYDOWN: return CBKeyDown(hwnd, wParam, lParam);
|
|
case WM_CHAR: return CBChar(hwnd, wParam, lParam);
|
|
case WM_SETFONT: return CBSetFont(hwnd, wParam, lParam);
|
|
case WM_SETREDRAW: return CBSetRedraw(hwnd, wParam, lParam);
|
|
case WM_PAINT: return CBPaint(hwnd, wParam, lParam);
|
|
case WM_GETTEXT: return CBGetText( hwnd, wParam, lParam);
|
|
case WM_LBUTTONDOWN: return CBLButtonDown(hwnd, wParam, lParam);
|
|
case WM_SETFOCUS: return CBSetFocus(hwnd, wParam, lParam);
|
|
case WM_KILLFOCUS: return CBKillFocus(hwnd, wParam, lParam);
|
|
case WM_SIZE: return CBCheckSize(hwnd);
|
|
case WM_COMMAND: return CBCommand(hwnd, wParam, lParam);
|
|
case CB_RESETCONTENT16: return CBResetContent(hwnd, wParam, lParam);
|
|
case CB_DIR16: return CBDir(hwnd, wParam, lParam);
|
|
case CB_ADDSTRING16: return CBAddString(hwnd, wParam, lParam);
|
|
case CB_INSERTSTRING16: return CBInsertString(hwnd, wParam, lParam);
|
|
case CB_DELETESTRING16: return CBDeleteString(hwnd, wParam, lParam);
|
|
case CB_FINDSTRING16: return CBFindString(hwnd, wParam, lParam);
|
|
case CB_GETCOUNT16: return CBGetCount(hwnd, wParam, lParam);
|
|
case CB_GETCURSEL16: return CBGetCurSel(hwnd, wParam, lParam);
|
|
case CB_GETITEMDATA16: return CBGetItemData(hwnd, wParam, lParam);
|
|
case CB_GETITEMHEIGHT16: return CBGetItemHeight(hwnd, wParam, lParam);
|
|
case CB_GETLBTEXT16: return CBGetLBText(hwnd, wParam, lParam);
|
|
case CB_GETLBTEXTLEN16: return CBGetLBTextLen(hwnd, wParam, lParam);
|
|
case CB_SELECTSTRING16: return CBSelectString(hwnd, wParam, lParam);
|
|
case CB_SETITEMDATA16: return CBSetItemData(hwnd, wParam, lParam);
|
|
case CB_SETCURSEL16: return CBSetCurSel(hwnd, wParam, lParam);
|
|
case CB_SETITEMHEIGHT16: return CBSetItemHeight(hwnd, wParam, lParam);
|
|
case CB_SHOWDROPDOWN16: return CBShowDropDown(hwnd, wParam, lParam);
|
|
case CB_GETEDITSEL16: return CBGetEditSel(hwnd, wParam, lParam);
|
|
case CB_SETEDITSEL16: return CBSetEditSel(hwnd, wParam, lParam);
|
|
case CB_FINDSTRINGEXACT16: return CBFindStringExact(hwnd, wParam, lParam);
|
|
}
|
|
return DefWindowProc16(hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/* ComboLBox code starts here */
|
|
|
|
HWND CLBoxGetCombo(HWND hwnd)
|
|
{
|
|
return (HWND)GetWindowLong32A(hwnd,0);
|
|
}
|
|
|
|
LPHEADLIST CLBoxGetListHeader(HWND hwnd)
|
|
{
|
|
return ComboGetListHeader(CLBoxGetCombo(hwnd));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLCreate
|
|
*/
|
|
static LRESULT CBLCreate( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
CREATESTRUCT16 *createStruct = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
|
|
SetWindowLong32A(hwnd,0,(LONG)createStruct->lpCreateParams);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLGetDlgCode
|
|
*/
|
|
static LRESULT CBLGetDlgCode( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
return DLGC_WANTARROWS | DLGC_WANTCHARS;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLKeyDown
|
|
*/
|
|
static LRESULT CBLKeyDown( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
WORD newFocused = lphl->ItemFocused;
|
|
|
|
switch(wParam) {
|
|
case VK_HOME:
|
|
newFocused = 0;
|
|
break;
|
|
case VK_END:
|
|
newFocused = lphl->ItemsCount - 1;
|
|
break;
|
|
case VK_UP:
|
|
if (newFocused > 0) newFocused--;
|
|
break;
|
|
case VK_DOWN:
|
|
newFocused++;
|
|
break;
|
|
case VK_PRIOR:
|
|
if (newFocused > lphl->ItemsVisible) {
|
|
newFocused -= lphl->ItemsVisible;
|
|
} else {
|
|
newFocused = 0;
|
|
}
|
|
break;
|
|
case VK_NEXT:
|
|
newFocused += lphl->ItemsVisible;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if (newFocused >= lphl->ItemsCount)
|
|
newFocused = lphl->ItemsCount - 1;
|
|
|
|
ListBoxSetCurSel(lphl, newFocused);
|
|
ListBoxSendNotification(lphl, CBN_SELCHANGE);
|
|
SendMessage16(GetParent16(hwnd), WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
|
|
lphl->ItemFocused = newFocused;
|
|
ListBoxScrollToFocus(lphl);
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLChar
|
|
*/
|
|
static LRESULT CBLChar( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLPaint
|
|
*/
|
|
static LRESULT CBLPaint( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
PAINTSTRUCT16 ps;
|
|
HBRUSH32 hBrush;
|
|
HFONT32 hOldFont;
|
|
WND * wndPtr = WIN_FindWndPtr(hwnd);
|
|
HWND combohwnd = CLBoxGetCombo(hwnd);
|
|
HDC16 hdc;
|
|
RECT16 rect;
|
|
int i, top, height;
|
|
|
|
top = 0;
|
|
hdc = BeginPaint16( hwnd, &ps );
|
|
|
|
if (!IsWindowVisible16(hwnd) || !lphl->bRedrawFlag) {
|
|
EndPaint16(hwnd, &ps);
|
|
return 0;
|
|
}
|
|
|
|
hOldFont = SelectObject32(hdc, lphl->hFont);
|
|
/* listboxes should be white */
|
|
hBrush = GetStockObject32(WHITE_BRUSH);
|
|
|
|
GetClientRect16(hwnd, &rect);
|
|
FillRect16(hdc, &rect, hBrush);
|
|
CBLCheckSize(hwnd);
|
|
|
|
lpls = lphl->lpFirst;
|
|
|
|
lphl->ItemsVisible = 0;
|
|
for(i = 0; i < lphl->ItemsCount; i++) {
|
|
if (lpls == NULL) break;
|
|
|
|
if (i >= lphl->FirstVisible) {
|
|
height = lpls->mis.itemHeight;
|
|
/* must have enough room to draw entire item */
|
|
if (top > (rect.bottom-height+1)) break;
|
|
|
|
lpls->itemRect.top = top;
|
|
lpls->itemRect.bottom = top + height;
|
|
lpls->itemRect.left = rect.left;
|
|
lpls->itemRect.right = rect.right;
|
|
|
|
dprintf_listbox(stddeb,"drawing item: %d %d %d %d %d\n",
|
|
rect.left,top,rect.right,top+height,lpls->itemState);
|
|
if (lphl->OwnerDrawn) {
|
|
ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 0);
|
|
if (lpls->itemState)
|
|
ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_SELECT, ODS_SELECTED);
|
|
} else {
|
|
ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
|
|
lpls->itemState);
|
|
}
|
|
if ((lphl->ItemFocused == i) && GetFocus32() == hwnd)
|
|
ListBoxDrawItem (combohwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, ODS_FOCUS);
|
|
|
|
top += height;
|
|
lphl->ItemsVisible++;
|
|
}
|
|
|
|
lpls = lpls->lpNext;
|
|
}
|
|
|
|
if (wndPtr->dwStyle & WS_VSCROLL)
|
|
SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
|
|
|
|
SelectObject32(hdc,hOldFont);
|
|
EndPaint16( hwnd, &ps );
|
|
return 0;
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLKillFocus
|
|
*/
|
|
static LRESULT CBLKillFocus( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
/* SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);*/
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLActivate
|
|
*/
|
|
static LRESULT CBLActivate( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
if (wParam == WA_INACTIVE)
|
|
SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLLButtonDown
|
|
*/
|
|
static LRESULT CBLLButtonDown( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
int y;
|
|
RECT16 rectsel;
|
|
|
|
/* SetFocus32(hwnd); */
|
|
SetCapture32(hwnd);
|
|
|
|
lphl->PrevFocused = lphl->ItemFocused;
|
|
|
|
y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
|
|
if (y == -1)
|
|
return 0;
|
|
|
|
ListBoxSetCurSel(lphl, y);
|
|
ListBoxGetItemRect(lphl, y, &rectsel);
|
|
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLLButtonUp
|
|
*/
|
|
static LRESULT CBLLButtonUp( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
|
|
if (GetCapture32() == hwnd) ReleaseCapture();
|
|
|
|
if(!lphl)
|
|
{
|
|
fprintf(stdnimp,"CBLLButtonUp: CLBoxGetListHeader returned NULL!\n");
|
|
}
|
|
else if (lphl->PrevFocused != lphl->ItemFocused)
|
|
{
|
|
SendMessage16(CLBoxGetCombo(hwnd),CB_SETCURSEL16,lphl->ItemFocused,0);
|
|
SendMessage16(GetParent16(hwnd), WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
|
|
ListBoxSendNotification(lphl, CBN_SELCHANGE);
|
|
}
|
|
|
|
SendMessage16(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN16,0,0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLMouseMove
|
|
*/
|
|
static LRESULT CBLMouseMove( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
short y;
|
|
WORD wRet;
|
|
RECT16 rect, rectsel;
|
|
|
|
y = SHIWORD(lParam);
|
|
wRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
|
|
ListBoxGetItemRect(lphl, wRet, &rectsel);
|
|
GetClientRect16(hwnd, &rect);
|
|
|
|
dprintf_combo(stddeb,"CBLMouseMove: hwnd %04x wp %x lp %lx y %d if %d wret %d %d,%d-%d,%d\n",
|
|
hwnd,wParam,lParam,y,lphl->ItemFocused,wRet,rectsel.left,rectsel.top,rectsel.right,rectsel.bottom);
|
|
|
|
if ((wParam & MK_LBUTTON) != 0) {
|
|
if (y < CBLMM_EDGE) {
|
|
if (lphl->FirstVisible > 0) {
|
|
lphl->FirstVisible--;
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
ListBoxSetCurSel(lphl, wRet);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
}
|
|
else if (y >= (rect.bottom-CBLMM_EDGE)) {
|
|
if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
|
|
lphl->FirstVisible++;
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
ListBoxSetCurSel(lphl, wRet);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
return 0;
|
|
}
|
|
}
|
|
else {
|
|
if ((short) wRet == lphl->ItemFocused) return 0;
|
|
ListBoxSetCurSel(lphl, wRet);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CBLVScroll
|
|
*/
|
|
static LRESULT CBLVScroll( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
|
|
{
|
|
LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
|
|
int y;
|
|
|
|
y = lphl->FirstVisible;
|
|
|
|
switch(wParam) {
|
|
case SB_LINEUP:
|
|
if (lphl->FirstVisible > 0)
|
|
lphl->FirstVisible--;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
lphl->FirstVisible++;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
if (lphl->FirstVisible > lphl->ItemsVisible) {
|
|
lphl->FirstVisible -= lphl->ItemsVisible;
|
|
} else {
|
|
lphl->FirstVisible = 0;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
lphl->FirstVisible += lphl->ItemsVisible;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
lphl->FirstVisible = LOWORD(lParam);
|
|
break;
|
|
}
|
|
|
|
if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
|
|
lphl->FirstVisible = ListMaxFirstVisible(lphl);
|
|
|
|
if (y != lphl->FirstVisible) {
|
|
SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
|
|
InvalidateRect32( hwnd, NULL, TRUE );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CBLCheckSize
|
|
*/
|
|
static BOOL CBLCheckSize(HWND hwnd)
|
|
{
|
|
LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
|
|
LPHEADLIST lphl = ComboGetListHeader(hwnd);
|
|
LPLISTSTRUCT lpls;
|
|
HWND hWndLBox;
|
|
RECT16 cRect,wRect,lRect,lwRect;
|
|
int totheight,dw;
|
|
char className[80];
|
|
|
|
GetClassName32A(hwnd,className,80);
|
|
fflush(stddeb);
|
|
if (strncmp(className,"COMBOBOX",8)) return FALSE;
|
|
if ((hWndLBox = lphc->hWndLBox) == 0) return FALSE;
|
|
dprintf_combo(stddeb,"CBLCheckSize headers hw %04x lb %04x name %s\n",
|
|
hwnd,hWndLBox,className);
|
|
|
|
GetClientRect16(hwnd,&cRect);
|
|
GetWindowRect16(hwnd,&wRect);
|
|
GetClientRect16(hWndLBox,&lRect);
|
|
GetWindowRect16(hWndLBox,&lwRect);
|
|
|
|
dprintf_combo(stddeb,"CBLCheckSize: init cRect %d,%d-%d,%d wRect %d,%d-%d,%d\n",
|
|
cRect.left,cRect.top,cRect.right,cRect.bottom,
|
|
wRect.left,wRect.top,wRect.right,wRect.bottom);
|
|
dprintf_combo(stddeb," lRect %d,%d-%d,%d lwRect %d,%d-%d,%d\n",
|
|
lRect.left,lRect.top,lRect.right,lRect.bottom,
|
|
lwRect.left,lwRect.top,lwRect.right,lwRect.bottom);
|
|
fflush(stddeb);
|
|
|
|
totheight = 0;
|
|
for (lpls=lphl->lpFirst; lpls != NULL; lpls=lpls->lpNext)
|
|
totheight += lpls->mis.itemHeight;
|
|
|
|
dw = cRect.right-cRect.left+2*SYSMETRICS_CXBORDER+SYSMETRICS_CXVSCROLL;
|
|
dw -= lwRect.right-lwRect.left;
|
|
dw -= SYSMETRICS_CXVSCROLL;
|
|
|
|
/* TODO: This isn't really what windows does */
|
|
if ((lRect.bottom-lRect.top < 3*lphl->StdItemHeight) || dw) {
|
|
dprintf_combo(stddeb," Changing; totHeight %d StdItemHght %d dw %d\n",
|
|
totheight,lphl->StdItemHeight,dw);
|
|
SetWindowPos32(hWndLBox, 0, lRect.left, lRect.top,
|
|
lwRect.right-lwRect.left+dw, totheight+2*SYSMETRICS_CYBORDER,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* ComboLBoxWndProc
|
|
*/
|
|
LRESULT ComboLBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
switch(message) {
|
|
case WM_CREATE: return CBLCreate(hwnd, wParam, lParam);
|
|
case WM_GETDLGCODE: return CBLGetDlgCode(hwnd, wParam, lParam);
|
|
case WM_KEYDOWN: return CBLKeyDown(hwnd, wParam, lParam);
|
|
case WM_CHAR: return CBLChar(hwnd, wParam, lParam);
|
|
case WM_PAINT: return CBLPaint(hwnd, wParam, lParam);
|
|
case WM_KILLFOCUS: return CBLKillFocus(hwnd, wParam, lParam);
|
|
case WM_ACTIVATE: return CBLActivate(hwnd, wParam, lParam);
|
|
case WM_LBUTTONDOWN: return CBLLButtonDown(hwnd, wParam, lParam);
|
|
case WM_LBUTTONUP: return CBLLButtonUp(hwnd, wParam, lParam);
|
|
case WM_MOUSEMOVE: return CBLMouseMove(hwnd, wParam, lParam);
|
|
case WM_VSCROLL: return CBLVScroll(hwnd, wParam, lParam);
|
|
case WM_SIZE: return CBLCheckSize(hwnd);
|
|
case WM_MOUSEACTIVATE: /* We don't want to be activated */
|
|
return MA_NOACTIVATE;
|
|
}
|
|
return DefWindowProc16(hwnd, message, wParam, lParam);
|
|
}
|