You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
873 lines
25 KiB
873 lines
25 KiB
/****************************** Module Header ********************************\
|
|
* Module Name: lb1.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* ListBox routines
|
|
*
|
|
* History:
|
|
* ??-???-???? ianja Ported from Win 3.0 sources
|
|
* 14-Feb-1991 mikeke Added Revalidation code
|
|
\*****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
LOOKASIDE ListboxLookaside;
|
|
|
|
|
|
/***************************************************************************\
|
|
* xxxLBoxCtlWndProc
|
|
*
|
|
* Window Procedure for ListBox AND ComboLBox control.
|
|
* NOTE: All window procedures are APIENTRY
|
|
* WARNING: This listbox code contains some internal messages and styles which
|
|
* are defined in combcom.h and in combcom.inc. They may be redefined
|
|
* (or renumbered) as needed to extend the windows API.
|
|
*
|
|
* History:
|
|
* 16-Apr-1992 beng Added LB_SETCOUNT
|
|
\***************************************************************************/
|
|
|
|
LRESULT APIENTRY ListBoxWndProcWorker(
|
|
PWND pwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
DWORD fAnsi)
|
|
{
|
|
HWND hwnd = HWq(pwnd);
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
LPRECT lprc;
|
|
PLBIV plb; /* List Box Instance Variable */
|
|
INT iSel; /* Index of selected item */
|
|
DWORD dw;
|
|
TL tlpwndParent;
|
|
UINT wFlags;
|
|
LPWSTR lpwsz = NULL;
|
|
LRESULT lReturn = 0;
|
|
static BOOL fInit = TRUE;
|
|
|
|
CheckLock(pwnd);
|
|
|
|
VALIDATECLASSANDSIZE(pwnd, FNID_LISTBOX);
|
|
INITCONTROLLOOKASIDE(&ListboxLookaside, LBIV, spwnd, 4);
|
|
|
|
/*
|
|
* Get the plb for the given window now since we will use it a lot in
|
|
* various handlers. This was stored using SetWindowLong(hwnd,0,plb)
|
|
* when the listbox was first created (by INITCONTROLLOOKASIDE above)
|
|
*/
|
|
plb = ((PLBWND)pwnd)->pLBIV;
|
|
|
|
/*
|
|
* Handle ANSI translations of input parameters
|
|
*/
|
|
if (fAnsi) {
|
|
switch (message) {
|
|
case LB_ADDSTRING:
|
|
case LB_ADDSTRINGUPPER:
|
|
case LB_ADDSTRINGLOWER:
|
|
case LB_FINDSTRING:
|
|
case LB_FINDSTRINGEXACT:
|
|
case LB_INSERTSTRING:
|
|
case LB_INSERTSTRINGUPPER:
|
|
case LB_INSERTSTRINGLOWER:
|
|
case LB_SELECTSTRING:
|
|
if (!plb->fHasStrings) {
|
|
break;
|
|
}
|
|
// Fall through...
|
|
case LB_ADDFILE:
|
|
case LB_DIR:
|
|
if (lParam) {
|
|
if (!MBToWCS((LPSTR)lParam, -1, &lpwsz, -1, TRUE))
|
|
return LB_ERR;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (lpwsz) {
|
|
lParam = (LPARAM)lpwsz;
|
|
}
|
|
}
|
|
|
|
switch (message) {
|
|
|
|
case LB_GETTOPINDEX: // Return index of top item displayed.
|
|
return plb->iTop;
|
|
|
|
case LB_SETTOPINDEX:
|
|
if (wParam && ((INT)wParam < 0 || (INT)wParam >= plb->cMac)) {
|
|
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
|
|
return LB_ERR;
|
|
}
|
|
if (plb->cMac) {
|
|
xxxNewITop(plb, (INT)wParam);
|
|
}
|
|
break;
|
|
|
|
case WM_STYLECHANGED:
|
|
plb->fRtoLReading = (TestWF(pwnd, WEFRTLREADING) != 0);
|
|
plb->fRightAlign = (TestWF(pwnd, WEFRIGHT) != 0);
|
|
xxxCheckRedraw(plb, FALSE, 0);
|
|
break;
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
|
|
/*
|
|
* If we are in the middle of creation, ignore this
|
|
* message because it will generate a WM_SIZE message.
|
|
* See xxxLBCreate().
|
|
*/
|
|
if (!plb->fIgnoreSizeMsg)
|
|
goto CallDWP;
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
|
|
/*
|
|
* If we are in the middle of creation, ignore size
|
|
* messages. See xxxLBCreate().
|
|
*/
|
|
if (!plb->fIgnoreSizeMsg)
|
|
xxxLBSize(plb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
ThreadLock(plb->spwndParent, &tlpwndParent);
|
|
FillWindow(HW(plb->spwndParent), hwnd, (HDC)wParam,
|
|
(HBRUSH)CTLCOLOR_LISTBOX);
|
|
ThreadUnlock(&tlpwndParent);
|
|
return TRUE;
|
|
|
|
case LB_RESETCONTENT:
|
|
xxxLBResetContent(plb);
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if (wParam == IDSYS_LBSEARCH) {
|
|
plb->iTypeSearch = 0;
|
|
NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
|
|
xxxInvertLBItem(plb, plb->iSel, TRUE);
|
|
break;
|
|
}
|
|
|
|
message = WM_MOUSEMOVE;
|
|
xxxTrackMouse(plb, message, plb->ptPrev);
|
|
break;
|
|
|
|
/*
|
|
* Fall through
|
|
*/
|
|
case WM_MOUSEMOVE:
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_LBUTTONDBLCLK:
|
|
{
|
|
POINT pt;
|
|
|
|
POINTSTOPOINT(pt, lParam);
|
|
xxxTrackMouse(plb, message, pt);
|
|
}
|
|
break;
|
|
|
|
case WM_MBUTTONDOWN:
|
|
EnterReaderModeHelper(hwnd);
|
|
break;
|
|
|
|
case WM_CAPTURECHANGED:
|
|
//
|
|
// Note that this message should be handled only on unexpected
|
|
// capture changes currently.
|
|
//
|
|
UserAssert(TestWF(pwnd, WFWIN40COMPAT));
|
|
if (plb->fCaptured)
|
|
xxxLBButtonUp(plb, LBUP_NOTIFY);
|
|
break;
|
|
|
|
case LBCB_STARTTRACK:
|
|
//
|
|
// Start tracking mouse moves in the listbox, setting capture
|
|
//
|
|
if (!plb->pcbox)
|
|
break;
|
|
|
|
plb->fCaptured = FALSE;
|
|
if (wParam) {
|
|
POINT pt;
|
|
|
|
POINTSTOPOINT(pt, lParam);
|
|
|
|
_ScreenToClient(pwnd, &pt);
|
|
xxxTrackMouse(plb, WM_LBUTTONDOWN, pt);
|
|
} else {
|
|
NtUserSetCapture(hwnd);
|
|
plb->fCaptured = TRUE;
|
|
plb->iLastSelection = plb->iSel;
|
|
}
|
|
break;
|
|
|
|
case LBCB_ENDTRACK:
|
|
// Kill capture, tracking, etc.
|
|
if (plb->fCaptured)
|
|
xxxLBButtonUp(plb, LBUP_RELEASECAPTURE | (wParam ? LBUP_SELCHANGE :
|
|
LBUP_RESETSELECTION));
|
|
break;
|
|
|
|
case WM_PRINTCLIENT:
|
|
xxxLBPaint(plb, (HDC) wParam, NULL);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if (wParam) {
|
|
hdc = (HDC) wParam;
|
|
lprc = NULL;
|
|
} else {
|
|
hdc = NtUserBeginPaint(hwnd, &ps);
|
|
lprc = &(ps.rcPaint);
|
|
}
|
|
|
|
if (IsLBoxVisible(plb))
|
|
xxxLBPaint(plb, hdc, lprc);
|
|
|
|
if (!wParam)
|
|
NtUserEndPaint(hwnd, &ps);
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
case WM_FINALDESTROY:
|
|
xxxDestroyLBox(plb, pwnd);
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
// DISABLED in Win 3.1 xxxUpdateWindow(pwnd);
|
|
CaretCreate(plb);
|
|
xxxLBSetCaret(plb, TRUE);
|
|
xxxNotifyOwner(plb, LBN_SETFOCUS);
|
|
|
|
/*
|
|
* We need to send this event even if the listbox isn't visible. See
|
|
* bug #88548.
|
|
*/
|
|
LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
/*
|
|
* Reset the wheel delta count.
|
|
*/
|
|
gcWheelDelta = 0;
|
|
|
|
xxxLBSetCaret(plb, FALSE);
|
|
xxxCaretDestroy(plb);
|
|
xxxNotifyOwner(plb, LBN_KILLFOCUS);
|
|
if (plb->iTypeSearch) {
|
|
plb->iTypeSearch = 0;
|
|
NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
|
|
}
|
|
if (plb->pszTypeSearch) {
|
|
UserLocalFree(plb->pszTypeSearch);
|
|
plb->pszTypeSearch = NULL;
|
|
}
|
|
break;
|
|
|
|
case WM_MOUSEWHEEL:
|
|
{
|
|
int cDetants;
|
|
int cPage;
|
|
int cLines;
|
|
RECT rc;
|
|
int windowWidth;
|
|
int cPos;
|
|
|
|
/*
|
|
* Don't handle zoom and datazoom.
|
|
*/
|
|
if (wParam & (MK_SHIFT | MK_CONTROL)) {
|
|
goto CallDWP;
|
|
}
|
|
|
|
lReturn = 1;
|
|
gcWheelDelta -= (short) HIWORD(wParam);
|
|
cDetants = gcWheelDelta / WHEEL_DELTA;
|
|
if ( cDetants != 0 &&
|
|
gpsi->ucWheelScrollLines > 0 &&
|
|
(pwnd->style & (WS_VSCROLL | WS_HSCROLL))) {
|
|
|
|
gcWheelDelta = gcWheelDelta % WHEEL_DELTA;
|
|
|
|
if (pwnd->style & WS_VSCROLL) {
|
|
cPage = max(1, (plb->cItemFullMax - 1));
|
|
cLines = cDetants *
|
|
(int) min((UINT) cPage, gpsi->ucWheelScrollLines);
|
|
|
|
cPos = max(0, min(plb->iTop + cLines, plb->cMac - 1));
|
|
if (cPos != plb->iTop) {
|
|
xxxLBoxCtlScroll(plb, SB_THUMBPOSITION, cPos);
|
|
xxxLBoxCtlScroll(plb, SB_ENDSCROLL, 0);
|
|
}
|
|
} else if (plb->fMultiColumn) {
|
|
cPage = max(1, plb->numberOfColumns);
|
|
cLines = cDetants * (int) min((UINT) cPage, gpsi->ucWheelScrollLines);
|
|
cPos = max(
|
|
0,
|
|
min((plb->iTop / plb->itemsPerColumn) + cLines,
|
|
plb->cMac - 1 - ((plb->cMac - 1) % plb->itemsPerColumn)));
|
|
|
|
if (cPos != plb->iTop) {
|
|
xxxLBoxCtlHScrollMultiColumn(plb, SB_THUMBPOSITION, cPos);
|
|
xxxLBoxCtlHScrollMultiColumn(plb, SB_ENDSCROLL, 0);
|
|
}
|
|
} else {
|
|
_GetClientRect(plb->spwnd, &rc);
|
|
windowWidth = rc.right;
|
|
cPage = max(plb->cxChar, (windowWidth / 3) * 2) /
|
|
plb->cxChar;
|
|
|
|
cLines = cDetants *
|
|
(int) min((UINT) cPage, gpsi->ucWheelScrollLines);
|
|
|
|
cPos = max(
|
|
0,
|
|
min(plb->xOrigin + (cLines * plb->cxChar),
|
|
plb->maxWidth));
|
|
|
|
if (cPos != plb->xOrigin) {
|
|
xxxLBoxCtlHScroll(plb, SB_THUMBPOSITION, cPos);
|
|
xxxLBoxCtlHScroll(plb, SB_ENDSCROLL, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_VSCROLL:
|
|
xxxLBoxCtlScroll(plb, LOWORD(wParam), HIWORD(wParam));
|
|
break;
|
|
|
|
case WM_HSCROLL:
|
|
xxxLBoxCtlHScroll(plb, LOWORD(wParam), HIWORD(wParam));
|
|
break;
|
|
|
|
case WM_GETDLGCODE:
|
|
return DLGC_WANTARROWS | DLGC_WANTCHARS;
|
|
|
|
case WM_CREATE:
|
|
return xxxLBCreate(plb, pwnd, (LPCREATESTRUCT) lParam);
|
|
|
|
case WM_SETREDRAW:
|
|
|
|
/*
|
|
* If wParam is nonzero, the redraw flag is set
|
|
* If wParam is zero, the flag is cleared
|
|
*/
|
|
xxxLBSetRedraw(plb, (wParam != 0));
|
|
break;
|
|
|
|
case WM_ENABLE:
|
|
xxxLBInvalidateRect(plb, NULL, !plb->OwnerDraw);
|
|
break;
|
|
|
|
case WM_SETFONT:
|
|
xxxLBSetFont(plb, (HANDLE)wParam, LOWORD(lParam));
|
|
break;
|
|
|
|
case WM_GETFONT:
|
|
return (LRESULT)plb->hFont;
|
|
|
|
case WM_DRAGSELECT:
|
|
case WM_DRAGLOOP:
|
|
case WM_DRAGMOVE:
|
|
case WM_DROPFILES:
|
|
ThreadLock(plb->spwndParent, &tlpwndParent);
|
|
lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
|
|
ThreadUnlock(&tlpwndParent);
|
|
return lReturn;
|
|
|
|
|
|
case WM_QUERYDROPOBJECT:
|
|
case WM_DROPOBJECT:
|
|
|
|
/*
|
|
* fix up control data, then pass message to parent
|
|
*/
|
|
LBDropObjectHandler(plb, (PDROPSTRUCT)lParam);
|
|
ThreadLock(plb->spwndParent, &tlpwndParent);
|
|
lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
|
|
ThreadUnlock(&tlpwndParent);
|
|
return lReturn;
|
|
|
|
case LB_GETITEMRECT:
|
|
return LBGetItemRect(plb, (INT)wParam, (LPRECT)lParam);
|
|
|
|
case LB_GETITEMDATA:
|
|
return LBGetItemData(plb, (INT)wParam); // wParam = item index
|
|
|
|
case LB_SETITEMDATA:
|
|
|
|
/*
|
|
* wParam is item index
|
|
*/
|
|
return LBSetItemData(plb, (INT)wParam, lParam);
|
|
|
|
case LB_ADDSTRINGUPPER:
|
|
wFlags = UPPERCASE | LBI_ADD;
|
|
goto CallInsertItem;
|
|
|
|
case LB_ADDSTRINGLOWER:
|
|
wFlags = LOWERCASE | LBI_ADD;
|
|
goto CallInsertItem;
|
|
|
|
case LB_ADDSTRING:
|
|
wFlags = LBI_ADD;
|
|
goto CallInsertItem;
|
|
|
|
case LB_INSERTSTRINGUPPER:
|
|
wFlags = UPPERCASE;
|
|
goto CallInsertItem;
|
|
|
|
case LB_INSERTSTRINGLOWER:
|
|
wFlags = LOWERCASE;
|
|
goto CallInsertItem;
|
|
|
|
case LB_INSERTSTRING:
|
|
wFlags = 0;
|
|
CallInsertItem:
|
|
lReturn = ((LRESULT) xxxLBInsertItem(plb, (LPWSTR) lParam, (int) wParam, wFlags));
|
|
break;
|
|
|
|
case LB_INITSTORAGE:
|
|
return xxxLBInitStorage(plb, fAnsi, (INT)wParam, (INT)lParam);
|
|
|
|
case LB_DELETESTRING:
|
|
return xxxLBoxCtlDelete(plb, (INT)wParam);
|
|
|
|
case LB_DIR:
|
|
/*
|
|
* wParam - Dos attribute value.
|
|
* lParam - Points to a file specification string
|
|
*/
|
|
lReturn = xxxLbDir(plb, (INT)wParam, (LPWSTR)lParam);
|
|
break;
|
|
|
|
case LB_ADDFILE:
|
|
lReturn = xxxLbInsertFile(plb, (LPWSTR)lParam);
|
|
break;
|
|
|
|
case LB_SETSEL:
|
|
return xxxLBSetSel(plb, (wParam != 0), (INT)lParam);
|
|
|
|
case LB_SETCURSEL:
|
|
/*
|
|
* If window obscured, update so invert will work correctly
|
|
*/
|
|
// DISABLED in Win 3.1 xxxUpdateWindow(pwnd);
|
|
return xxxLBSetCurSel(plb, (INT)wParam);
|
|
|
|
case LB_GETSEL:
|
|
if (wParam >= (UINT) plb->cMac)
|
|
return((LRESULT) LB_ERR);
|
|
|
|
return IsSelected(plb, (INT)wParam, SELONLY);
|
|
|
|
case LB_GETCURSEL:
|
|
if (plb->wMultiple == SINGLESEL) {
|
|
return plb->iSel;
|
|
}
|
|
return plb->iSelBase;
|
|
|
|
case LB_SELITEMRANGE:
|
|
if (plb->wMultiple == SINGLESEL) {
|
|
/*
|
|
* Can't select a range if only single selections are enabled
|
|
*/
|
|
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SELITEMRANGE");
|
|
return LB_ERR;
|
|
}
|
|
|
|
xxxLBSelRange(plb, LOWORD(lParam), HIWORD(lParam), (wParam != 0));
|
|
break;
|
|
|
|
case LB_SELITEMRANGEEX:
|
|
if (plb->wMultiple == SINGLESEL) {
|
|
/*
|
|
* Can't select a range if only single selections are enabled
|
|
*/
|
|
RIPERR0(ERROR_INVALID_LB_MESSAGE, RIP_VERBOSE,"LB_SELITEMRANGEEX:Can't select a range if only single selections are enabled");
|
|
return LB_ERR;
|
|
} else {
|
|
BOOL fHighlight = ((DWORD)lParam > (DWORD)wParam);
|
|
if (fHighlight == FALSE) {
|
|
ULONG_PTR temp = lParam;
|
|
lParam = wParam;
|
|
wParam = temp;
|
|
}
|
|
xxxLBSelRange(plb, (INT)wParam, (INT)lParam, fHighlight);
|
|
}
|
|
break;
|
|
|
|
case LB_GETTEXTLEN:
|
|
if (lParam != 0) {
|
|
RIPMSG1(RIP_WARNING, "LB_GETTEXTLEN with lParam = %lx\n", lParam);
|
|
}
|
|
lReturn = LBGetText(plb, TRUE, fAnsi, (INT)wParam, NULL);
|
|
break;
|
|
|
|
case LB_GETTEXT:
|
|
lReturn = LBGetText(plb, FALSE, fAnsi, (INT)wParam, (LPWSTR)lParam);
|
|
break;
|
|
|
|
case LB_GETCOUNT:
|
|
// Lotus Approach calls CallWndProc(ListWndProc, LB_GETCOUNT,...)
|
|
// on a window that doesn't have a plb yet. So, we need to make
|
|
// this check. Bug #6675 - 11/7/94 --
|
|
if(plb)
|
|
return((LRESULT) plb->cMac);
|
|
else
|
|
return(0);
|
|
|
|
case LB_SETCOUNT:
|
|
return xxxLBSetCount(plb, (INT)wParam);
|
|
|
|
case LB_SELECTSTRING:
|
|
case LB_FINDSTRING:
|
|
iSel = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, PREFIX, TRUE);
|
|
if (message == LB_FINDSTRING || iSel == LB_ERR) {
|
|
lReturn = iSel;
|
|
} else {
|
|
lReturn = xxxLBSetCurSel(plb, iSel);
|
|
}
|
|
break;
|
|
|
|
case LB_GETLOCALE:
|
|
return plb->dwLocaleId;
|
|
|
|
case LB_SETLOCALE:
|
|
|
|
/*
|
|
* Validate locale
|
|
*/
|
|
wParam = ConvertDefaultLocale((LCID)wParam);
|
|
if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
|
|
return LB_ERR;
|
|
|
|
dw = plb->dwLocaleId;
|
|
plb->dwLocaleId = (DWORD)wParam;
|
|
return dw;
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
/*
|
|
* IanJa: Use LOWORD() to get low 16-bits of wParam - this should
|
|
* work for Win16 & Win32. The value obtained is the virtual key
|
|
*/
|
|
xxxLBoxCtlKeyInput(plb, message, LOWORD(wParam));
|
|
break;
|
|
|
|
case WM_CHAR:
|
|
xxxLBoxCtlCharInput(plb, LOWORD(wParam), fAnsi);
|
|
break;
|
|
|
|
case LB_GETSELITEMS:
|
|
case LB_GETSELCOUNT:
|
|
|
|
/*
|
|
* IanJa/Win32 should this be LPWORD now?
|
|
*/
|
|
return LBoxGetSelItems(plb, (message == LB_GETSELCOUNT), (INT)wParam,
|
|
(LPINT)lParam);
|
|
|
|
case LB_SETTABSTOPS:
|
|
|
|
/*
|
|
* IanJa/Win32: Tabs given by array of INT for backwards compatability
|
|
*/
|
|
return LBSetTabStops(plb, (INT)wParam, (LPINT)lParam);
|
|
|
|
case LB_GETHORIZONTALEXTENT:
|
|
|
|
/*
|
|
* Return the max width of the listbox used for horizontal scrolling
|
|
*/
|
|
return plb->maxWidth;
|
|
|
|
case LB_SETHORIZONTALEXTENT:
|
|
|
|
/*
|
|
* Set the max width of the listbox used for horizontal scrolling
|
|
*/
|
|
if (plb->maxWidth != (INT)wParam) {
|
|
plb->maxWidth = (INT)wParam;
|
|
|
|
/*
|
|
* When horizontal extent is set, Show/hide the scroll bars.
|
|
* NOTE: LBShowHideScrollBars() takes care if Redraw is OFF.
|
|
* Fix for Bug #2477 -- 01/14/91 -- SANKAR --
|
|
*/
|
|
xxxLBShowHideScrollBars(plb); //Try to show or hide scroll bars
|
|
if (plb->fHorzBar && plb->fRightAlign && !(plb->fMultiColumn || plb->OwnerDraw)) {
|
|
/*
|
|
* origin to right
|
|
*/
|
|
xxxLBoxCtlHScroll(plb, SB_BOTTOM, 0);
|
|
}
|
|
}
|
|
break; /* originally returned register ax (message) ! */
|
|
|
|
case LB_SETCOLUMNWIDTH:
|
|
|
|
/*
|
|
* Set the width of a column in a multicolumn listbox
|
|
*/
|
|
plb->cxColumn = (INT)wParam;
|
|
LBCalcItemRowsAndColumns(plb);
|
|
if (IsLBoxVisible(plb))
|
|
NtUserInvalidateRect(hwnd, NULL, TRUE);
|
|
xxxLBShowHideScrollBars(plb);
|
|
break;
|
|
|
|
case LB_SETANCHORINDEX:
|
|
if ((INT)wParam >= plb->cMac) {
|
|
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETANCHORINDEX");
|
|
return LB_ERR;
|
|
}
|
|
plb->iMouseDown = (INT)wParam;
|
|
plb->iLastMouseMove = (INT)wParam;
|
|
xxxInsureVisible(plb, (int) wParam, (BOOL)(lParam != 0));
|
|
break;
|
|
|
|
case LB_GETANCHORINDEX:
|
|
return plb->iMouseDown;
|
|
|
|
case LB_SETCARETINDEX:
|
|
if ( (plb->iSel == -1) || ((plb->wMultiple != SINGLESEL) &&
|
|
(plb->cMac > (INT)wParam))) {
|
|
|
|
/*
|
|
* Set's the iSelBase to the wParam
|
|
* if lParam, then don't scroll if partially visible
|
|
* else scroll into view if not fully visible
|
|
*/
|
|
xxxInsureVisible(plb, (INT)wParam, (BOOL)LOWORD(lParam));
|
|
xxxSetISelBase(plb, (INT)wParam);
|
|
break;
|
|
} else {
|
|
if ((INT)wParam >= plb->cMac) {
|
|
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETCARETINDEX");
|
|
}
|
|
return LB_ERR;
|
|
}
|
|
break;
|
|
|
|
case LB_GETCARETINDEX:
|
|
return plb->iSelBase;
|
|
|
|
case LB_SETITEMHEIGHT:
|
|
case LB_GETITEMHEIGHT:
|
|
return LBGetSetItemHeightHandler(plb, message, (INT)wParam, LOWORD(lParam));
|
|
break;
|
|
|
|
case LB_FINDSTRINGEXACT:
|
|
lReturn = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, EQ, TRUE);
|
|
break;
|
|
|
|
case LB_ITEMFROMPOINT: {
|
|
POINT pt;
|
|
BOOL bOutside;
|
|
DWORD dwItem;
|
|
|
|
POINTSTOPOINT(pt, lParam);
|
|
bOutside = ISelFromPt(plb, pt, &dwItem);
|
|
UserAssert(bOutside == 1 || bOutside == 0);
|
|
return (LRESULT)MAKELONG(dwItem, bOutside);
|
|
}
|
|
|
|
case LBCB_CARETON:
|
|
|
|
/*
|
|
* Internal message for combo box support
|
|
*/
|
|
CaretCreate(plb);
|
|
// Set up the caret in the proper location for drop downs.
|
|
plb->iSelBase = plb->iSel;
|
|
xxxLBSetCaret(plb, TRUE);
|
|
|
|
/*
|
|
* We need to send this event even if the listbox isn't visible. See
|
|
* bug #88548. Also see 355612.
|
|
*/
|
|
if (_IsWindowVisible(pwnd) || (GetFocus() == hwnd)) {
|
|
LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
|
|
}
|
|
|
|
return(plb->iSel);
|
|
|
|
case LBCB_CARETOFF:
|
|
|
|
/*
|
|
* Internal message for combo box support
|
|
*/
|
|
xxxLBSetCaret(plb, FALSE);
|
|
xxxCaretDestroy(plb);
|
|
break;
|
|
|
|
case LB_GETLISTBOXINFO:
|
|
return NtUserGetListBoxInfo(hwnd);
|
|
|
|
case WM_NCCREATE:
|
|
if ((pwnd->style & LBS_MULTICOLUMN) && (pwnd->style & WS_VSCROLL))
|
|
{
|
|
DWORD mask = WS_VSCROLL;
|
|
DWORD flags = 0;
|
|
if (!TestWF(pwnd, WFWIN40COMPAT)) {
|
|
mask |= WS_HSCROLL;
|
|
flags = WS_HSCROLL;
|
|
}
|
|
NtUserAlterWindowStyle(hwnd, mask, flags);
|
|
}
|
|
goto CallDWP;
|
|
|
|
default:
|
|
CallDWP:
|
|
return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
|
|
}
|
|
|
|
/*
|
|
* Handle translation of ANSI output data and free buffer
|
|
*/
|
|
if (lpwsz) {
|
|
UserLocalFree(lpwsz);
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
\***************************************************************************/
|
|
|
|
LRESULT WINAPI ListBoxWndProcA(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PWND pwnd;
|
|
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
|
|
return (0L);
|
|
}
|
|
|
|
/*
|
|
* If the control is not interested in this message,
|
|
* pass it to DefWindowProc.
|
|
*/
|
|
if (!FWINDOWMSG(message, FNID_LISTBOX))
|
|
return DefWindowProcWorker(pwnd, message, wParam, lParam, TRUE);
|
|
|
|
return ListBoxWndProcWorker(pwnd, message, wParam, lParam, TRUE);
|
|
}
|
|
|
|
LRESULT WINAPI ListBoxWndProcW(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PWND pwnd;
|
|
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
|
|
return (0L);
|
|
}
|
|
|
|
/*
|
|
* If the control is not interested in this message,
|
|
* pass it to DefWindowProc.
|
|
*/
|
|
if (!FWINDOWMSG(message, FNID_LISTBOX))
|
|
return DefWindowProcWorker(pwnd, message, wParam, lParam, FALSE);
|
|
|
|
return ListBoxWndProcWorker(pwnd, message, wParam, lParam, FALSE);
|
|
}
|
|
|
|
LRESULT WINAPI ComboListBoxWndProcA(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PWND pwnd;
|
|
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
|
|
return (0L);
|
|
}
|
|
|
|
/*
|
|
* If the control is not interested in this message,
|
|
* pass it to DefWindowProc.
|
|
*/
|
|
if (!FWINDOWMSG(message, FNID_LISTBOX))
|
|
return DefWindowProcWorker(pwnd, message, wParam, lParam, TRUE);
|
|
|
|
return ListBoxWndProcWorker(pwnd, message, wParam, lParam, TRUE);
|
|
}
|
|
|
|
LRESULT WINAPI ComboListBoxWndProcW(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PWND pwnd;
|
|
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
|
|
return (0L);
|
|
}
|
|
|
|
/*
|
|
* If the control is not interested in this message,
|
|
* pass it to DefWindowProc.
|
|
*/
|
|
if (!FWINDOWMSG(message, FNID_LISTBOX))
|
|
return DefWindowProcWorker(pwnd, message, wParam, lParam, FALSE);
|
|
|
|
return ListBoxWndProcWorker(pwnd, message, wParam, lParam, FALSE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* GetLpszItem
|
|
*
|
|
* Returns a far pointer to the string belonging to item sItem
|
|
* ONLY for Listboxes maintaining their own strings (pLBIV->fHasStrings == TRUE)
|
|
*
|
|
* History:
|
|
\***************************************************************************/
|
|
|
|
LPWSTR GetLpszItem(
|
|
PLBIV pLBIV,
|
|
INT sItem)
|
|
{
|
|
LONG offsz;
|
|
lpLBItem plbi;
|
|
|
|
if (sItem < 0 || sItem >= pLBIV->cMac) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER,
|
|
RIP_WARNING,
|
|
"Invalid parameter \"sItem\" (%ld) to GetLpszItem",
|
|
sItem);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* get pointer to item index array
|
|
* NOTE: NOT OWNERDRAW
|
|
*/
|
|
plbi = (lpLBItem)(pLBIV->rgpch);
|
|
offsz = plbi[sItem].offsz;
|
|
return (LPWSTR)((PBYTE)(pLBIV->hStrings) + offsz);
|
|
}
|