Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1280 lines
34 KiB

#include "ctlspriv.h"
#define DXTEXTOFFSET (dxButton+2)
#define SPACESTRLEN 20
#define FLAG_NODEL 0x8000
#define FLAG_HIDDEN 0x4000
#define FLAG_ALLFLAGS (FLAG_NODEL|FLAG_HIDDEN)
typedef struct { // instance data for toolbar edit dialog
HWND hwndToolbar; // toolbar this is for
int iPos; // position to insert into
} ADJUSTDLGDATA, FAR *LPADJUSTDLGDATA;
typedef struct {
HWND hwndToolbar;
PTBSTATE pTBState;
} TBSTUFF, FAR *LPTBSTUFF;
extern int dxButton;
extern int dyButton;
extern int dyBitmap;
extern int dxButtonSep;
extern int nSelectedBM;
extern HDC hdcGlyphs;
extern HDC hdcMono;
extern HDC hdcOffScreen;
extern HBITMAP hbmMono;
extern HBITMAP hbmOffScreen;
extern TCHAR szToolbarClass[];
extern TCHAR szNull[];
static TCHAR szSampleText[] = TEXT("W");
static TCHAR szNumButtons[] = TEXT("NumButtons");
static struct {
TBBUTTON tbButton;
TCHAR szDescription[20];
} aiTemp;
extern DWORD rgbFace;
extern DWORD rgbShadow;
extern DWORD rgbHilight;
extern DWORD rgbFrame;
extern UINT uDragListMsg;
Static INT
GetPrevButton(PTBSTATE pTBState, int iPos)
{
// This means to delete the preceding space
for (--iPos; ; --iPos) {
if (iPos < 0)
break;
if (!(pTBState->Buttons[iPos].fsState & TBSTATE_HIDDEN))
break;
}
return(iPos);
}
VOID
MoveButton(HWND hwndToolbar, PTBSTATE pTBState, INT nSource)
{
HWND hwndParent;
UINT uiID;
INT nDest;
HCURSOR hCursor;
MSG msg;
// You can't move separators like this
if (nSource < 0)
return;
hwndParent = pTBState->hwndCommand;
uiID = GetWindowLong(hwndToolbar, GWL_ID);
// Make sure it is all right to "delete" the selected button
if (!SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, nSource, TBN_QUERYDELETE)))
return;
SetCapture(hwndToolbar);
hCursor = SetCursor(LoadCursor(hInst, (LPTSTR) MAKEINTRESOURCE(IDC_MOVEBUTTON)));
while (1) {
while (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE|PM_NOYIELD))
;
switch (msg.message) {
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
break;
case WM_LBUTTONUP:
if ((UINT)HIWORD(msg.lParam) > (UINT)dyButton) {
// If the button was dragged off the toolbar, delete it.
DeleteSrcButton:
SendMessage(hwndToolbar, TB_DELETEBUTTON, nSource, 0L);
SendMessage (hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, hwndToolbar, TBN_TOOLBARCHANGE));
} else {
// Add half a button to X so that it looks like it is centered
// over the target button.
nDest = TBHitTest (pTBState, LOWORD(msg.lParam) + dxButton / 2,
HIWORD(msg.lParam));
if (nDest < 0)
nDest = -1 - nDest;
if (nDest == nSource) {
// This means to delete the preceding space
nSource = GetPrevButton(pTBState, nSource);
if (nSource < 0)
goto AbortMove;
if ((pTBState->Buttons[nSource].fsStyle&TBSTYLE_SEP)
&& SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, nSource, TBN_QUERYDELETE)))
goto DeleteSrcButton;
} else if (nDest == nSource+1) {
// This means to add a preceding space
--nDest;
if (SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,nDest, TBN_QUERYINSERT))) {
aiTemp.tbButton.iBitmap = 0;
aiTemp.tbButton.fsState = 0;
aiTemp.tbButton.fsStyle = TBSTYLE_SEP;
goto InsertSrcButton;
}
}
else if (SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,nDest, TBN_QUERYINSERT))) {
// This is a normal move operation
aiTemp.tbButton = pTBState->Buttons[nSource];
SendMessage(hwndToolbar, TB_DELETEBUTTON, nSource, 0L);
if (nDest > nSource)
--nDest;
InsertSrcButton:
SendMessage (hwndToolbar, TB_INSERTBUTTON, nDest,
(LPARAM)(LPTBBUTTON)&aiTemp.tbButton);
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,hwndToolbar, TBN_TOOLBARCHANGE));
} else {
AbortMove:
;
}
}
goto AllDone;
case WM_RBUTTONDOWN:
goto AbortMove;
default:
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
AllDone:
SetCursor(hCursor);
ReleaseCapture();
}
#define GNI_HIGH 0x0001
#define GNI_LOW 0x0002
Static INT
GetNearestInsert(HWND hwndParent, UINT uiID, INT iPos,
INT iNumButtons, UINT uFlags)
{
INT i;
BOOL bKeepTrying;
// Find the nearest index where we can actually insert items
for (i = iPos; ; ++i, --iPos) {
bKeepTrying = FALSE;
// Notice we favor going high if both flags are set
if ((uFlags & GNI_HIGH) && i <= iNumButtons) {
bKeepTrying = TRUE;
if (SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,i, TBN_QUERYINSERT)))
return(i);
}
if ((uFlags & GNI_LOW) && iPos >= 0) {
bKeepTrying = TRUE;
if (SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,i, TBN_QUERYINSERT)))
return(iPos);
}
if (!bKeepTrying)
return(-1); /* There was no place to add buttons. */
}
}
Static BOOL
InitAdjustDlg(HWND hDlg, HWND hwndToolbar, int iPos)
{
HDC hDC;
HFONT hFont;
HWND hwndParent, hwndCurrent, hwndNew;
PTBSTATE pTBState;
PTBBUTTON ptbButton;
SIZE Size;
UINT uiID;
int i, nItem, nWid, nMaxWid;
HANDLE hInfo;
LPADJUSTINFO lpInfo;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
pTBState->hdlgCust = hDlg;
hwndParent = pTBState->hwndCommand;
uiID = GetWindowLong(hwndToolbar, GWL_ID);
iPos = GetNearestInsert(hwndParent, uiID, iPos, pTBState->iNumButtons,
GNI_HIGH|GNI_LOW);
if (iPos < 0)
return(FALSE);
hwndCurrent = GetDlgItem(hDlg, IDC_CURRENT);
SendMessage(hwndCurrent, LB_RESETCONTENT, 0, 0L);
hwndNew = GetDlgItem(hDlg, IDC_BUTTONLIST);
SendMessage(hwndNew, LB_RESETCONTENT, 0, 0L);
for (i = 0, ptbButton = pTBState->Buttons; i < pTBState->iNumButtons; ++i, ++ptbButton) {
UINT uFlags;
uFlags = 0;
if (!SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,i, TBN_QUERYDELETE)))
uFlags |= FLAG_NODEL;
if (ptbButton->fsState & TBSTATE_HIDDEN)
uFlags |= FLAG_HIDDEN;
if ((INT)SendMessage(hwndCurrent, LB_ADDSTRING, 0, (LPARAM)szNull) != i)
return(FALSE);
// Note: A negative number in the LOWORD indicates a separator;
// otherwise it is the bitmap index.
SendMessage(hwndCurrent, LB_SETITEMDATA, i,
MAKELPARAM(ptbButton->fsStyle&TBSTYLE_SEP ? -1:ptbButton->iBitmap,
uFlags));
}
// Add a dummy "nodel" space at the end so things can be inserted at the end.
if ((INT)SendMessage(hwndCurrent, LB_ADDSTRING, 0,(LPARAM)szNull) == i)
SendMessage(hwndCurrent, LB_SETITEMDATA, i, MAKELPARAM(-1, FLAG_NODEL));
// Now add a space at the beginning of the "new" list.
if (SendMessage(hwndNew, LB_ADDSTRING, 0, (LPARAM)szNull) == LB_ERR)
return(FALSE);
SendMessage(hwndNew, LB_SETITEMDATA, 0, MAKELPARAM(-1, 0));
hDC = GetDC(hwndCurrent);
hFont = (HFONT)(int)SendMessage(hwndCurrent, WM_GETFONT, 0, 0L);
if (hFont)
hFont = SelectObject(hDC, hFont);
nMaxWid = 0;
for (i=0; ; ++i) {
hInfo = (HANDLE)(int)SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, i, TBN_ADJUSTINFO));
if (!hInfo)
break;
lpInfo = (LPADJUSTINFO) hInfo;
// Don't show separators
if (!(lpInfo->tbButton.fsStyle & TBSTYLE_SEP)) {
// Get the maximum width of a string.
GetTextExtentPoint(hDC, lpInfo->szDescription,
lstrlen(lpInfo->szDescription), &Size);
nWid = Size.cx;
if (nMaxWid < nWid)
nMaxWid = nWid;
nItem = PositionFromID(pTBState, lpInfo->tbButton.idCommand);
if (nItem < 0) {
// Don't show hidden buttons
if (!(lpInfo->tbButton.fsState&TBSTATE_HIDDEN)) {
nItem = (int)SendMessage(hwndNew, LB_ADDSTRING, 0,
(LPARAM)lpInfo->szDescription);
if (nItem != LB_ERR)
SendMessage(hwndNew, LB_SETITEMDATA, nItem,
MAKELPARAM(lpInfo->tbButton.iBitmap, i));
}
} else {
DWORD dwTemp;
// Preserve the flags and bitmap.
dwTemp = SendMessage(hwndCurrent,LB_GETITEMDATA,nItem,0L);
SendMessage(hwndCurrent, LB_DELETESTRING, nItem, 0L);
if ((INT)SendMessage(hwndCurrent, LB_INSERTSTRING, nItem,
(LPARAM)lpInfo->szDescription) != nItem) {
ReleaseDC(hwndCurrent, hDC);
return(FALSE);
}
SendMessage(hwndCurrent, LB_SETITEMDATA, nItem,
MAKELPARAM(LOWORD(dwTemp), HIWORD(dwTemp)|i));
}
}
}
if (hFont)
SelectObject(hDC, hFont);
ReleaseDC(hwndCurrent, hDC);
nMaxWid += DXTEXTOFFSET + 1;
SendMessage(hwndNew, LB_SETHORIZONTALEXTENT, nMaxWid, 0L);
SendMessage(hwndCurrent, LB_SETHORIZONTALEXTENT, nMaxWid, 0L);
//
// EnableWindow(GetDlgItem(hDlg, IDC_HELP), FALSE);
//
SendMessage(hwndNew, LB_SETCURSEL, 0, 0L);
SendMessage(hwndCurrent, LB_SETCURSEL, iPos, 0L);
SendMessage(hDlg, WM_COMMAND,
GET_WM_COMMAND_MPS(IDC_CURRENT,hwndCurrent, LBN_SELCHANGE));
return(TRUE);
}
Static VOID
PaintAdjustLine(DRAWITEMSTRUCT FAR *lpdis,
HWND hwndToolbar)
{
HDC hdc = lpdis->hDC;
HWND hwndList = lpdis->hwndItem;
LPTSTR pszText;
RECT rc = lpdis->rcItem;
INT i, nBitmap, nLen, nItem = lpdis->itemID;
COLORREF oldBkColor, oldTextColor;
BOOL bSelected, bHasFocus;
HBRUSH hBrush;
WORD wHeight;
if (lpdis->CtlID!=IDC_BUTTONLIST && lpdis->CtlID!=IDC_CURRENT)
return;
nBitmap = LOWORD(lpdis->itemData);
// Fix up separators: 0xffff is non-neg!
if (0xffff == nBitmap)
nBitmap = -1;
if (nBitmap < 0)
nLen = SPACESTRLEN;
else {
nLen = (int)SendMessage(hwndList, LB_GETTEXTLEN, nItem, 0L);
if (nLen < 0)
return;
}
pszText = (LPTSTR)LocalAlloc(LMEM_FIXED, ByteCountOf(nLen + 1));
if (!pszText)
return;
if (nBitmap < 0)
nLen = LoadString(hInst, IDS_SPACE, pszText, SPACESTRLEN);
else
SendMessage(hwndList, LB_GETTEXT, nItem, (LPARAM)pszText);
if (lpdis->itemAction != ODA_FOCUS) {
SIZE Size;
// We don't care about focus if the item is not selected.
bSelected = lpdis->itemState & ODS_SELECTED;
if (bSelected)
bHasFocus = GetFocus() == hwndList;
if (HIWORD(lpdis->itemData) & (FLAG_NODEL|FLAG_HIDDEN))
i = COLOR_GRAYTEXT;
else if (bSelected && bHasFocus)
i = COLOR_HIGHLIGHTTEXT;
else
i = COLOR_WINDOWTEXT;
oldTextColor = SetTextColor(hdc, GetSysColor(i));
oldBkColor = SetBkColor(hdc, GetSysColor(bSelected && bHasFocus ?
COLOR_HIGHLIGHT : COLOR_WINDOW));
(VOID) GetTextExtentPoint(hdc, szSampleText, COUNTOF(szSampleText)-1, &Size);
wHeight = (WORD) Size.cy;
ExtTextOut(hdc, rc.left+DXTEXTOFFSET,
(rc.top+rc.bottom-wHeight)/2,
ETO_CLIPPED|ETO_OPAQUE, &rc, pszText, nLen, NULL);
if (nBitmap >= 0) {
PTBSTATE pTBState;
HBITMAP hbmOldGlyphs, hbmOldMono, hbmOldOffScreen;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
aiTemp.tbButton.iBitmap = nBitmap;
aiTemp.tbButton.fsStyle = TBSTYLE_BUTTON;
aiTemp.tbButton.fsState = (BYTE)
((HIWORD(lpdis->itemData)&FLAG_HIDDEN) ? 0 : TBSTATE_ENABLED);
// setup global stuff for fast painting
rgbFace = GetSysColor(COLOR_BTNFACE);
rgbShadow = GetSysColor(COLOR_BTNSHADOW);
rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
// We need to kick-start the bitmap selection process.
nSelectedBM = -1;
hbmOldGlyphs = SelectBM(hdcGlyphs, pTBState, 0);
if (!hbmOldGlyphs)
goto Error1;
hbmOldMono = SelectObject(hdcMono, hbmMono);
hbmOldOffScreen = SelectObject(hdcOffScreen, hbmOffScreen);
DrawButton(hdc, rc.left+1, rc.top+1,
dxButton, dyButton, pTBState, &aiTemp.tbButton);
if (hbmOldOffScreen)
SelectObject(hdcOffScreen, hbmOldOffScreen);
if (hbmOldMono)
SelectObject(hdcMono, hbmOldMono);
SelectObject(hdcGlyphs, hbmOldGlyphs);
Error1:
;
}
SetBkColor(hdc, oldBkColor);
SetTextColor(hdc, oldTextColor);
// Frame the item if it is selected but does not have the focus.
if (bSelected && !bHasFocus) {
hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
if (hBrush) {
nLen = rc.left + (int)SendMessage(hwndList,
LB_GETHORIZONTALEXTENT, 0, 0L);
if (rc.right < nLen)
rc.right = nLen;
FrameRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
}
}
}
if (lpdis->itemAction == ODA_FOCUS || (lpdis->itemState & ODS_FOCUS))
DrawFocusRect(hdc, &rc);
LocalFree((HLOCAL)pszText);
}
Static VOID
LBMoveButton(HWND hDlg, WORD wIDSrc, INT iPosSrc,
WORD wIDDst, int iPosDst, int iSelOffset)
{
HWND hwndToolbar, hwndParent, hwndSrc, hwndDst;
UINT uiID;
DWORD dwTemp;
LPTSTR pStr;
HANDLE hInfo = NULL;
LPADJUSTDLGDATA lpad;
PTBSTATE pTBState;
LPADJUSTINFO lpInfo;
INT iTopDst;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
hwndToolbar = lpad->hwndToolbar;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
hwndSrc = GetDlgItem(hDlg, wIDSrc);
hwndDst = GetDlgItem(hDlg, wIDDst);
hwndParent = pTBState->hwndCommand;
uiID = GetWindowLong(hwndToolbar, GWL_ID);
// Make sure we can delete the source and insert at the dest
dwTemp = SendMessage(hwndSrc, LB_GETITEMDATA, iPosSrc, 0L);
if (iPosSrc<0 || (HIWORD(dwTemp)&FLAG_NODEL))
return;
if (wIDDst==IDC_CURRENT && !SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,iPosDst, TBN_QUERYINSERT)))
return;
// Get the string for the source
pStr = (LPTSTR)LocalAlloc(LMEM_FIXED,
ByteCountOf(LOWORD(SendMessage(hwndSrc, LB_GETTEXTLEN, iPosSrc, 0L))+1));
if (!pStr)
return;
SendMessage(hwndSrc, LB_GETTEXT, iPosSrc, (LPARAM)pStr);
SendMessage(hwndDst, WM_SETREDRAW, 0, 0L);
iTopDst = (int)SendMessage(hwndDst, LB_GETTOPINDEX, 0, 0L);
// If we are inserting into the available button list, we need to determine
// the insertion point
if (wIDDst == IDC_BUTTONLIST) {
// Insert this back in the available list if this is not a space or a
// hidden button.
if (0xffff == (INT)LOWORD(dwTemp) || (HIWORD(dwTemp)&FLAG_HIDDEN)) {
iPosDst = 0;
goto DelTheSrc;
} else {
UINT uTemp;
uTemp = HIWORD(dwTemp) & ~(FLAG_ALLFLAGS);
// This just does a linear search for where to put the
// item. Slow, but this only happens when the user clicks
// the "Remove" button.
for (iPosDst=1; ; ++iPosDst) {
// Notice that this will break out when iPosDst is
// past the number of items, since -1 will be returned
if ((UINT)HIWORD(SendMessage(hwndDst, LB_GETITEMDATA,
iPosDst, 0L)) >= uTemp)
break;
}
}
} else if (iPosDst < 0)
goto CleanUp;
// Attempt to insert the new string
if ((INT)SendMessage(hwndDst, LB_INSERTSTRING, iPosDst, (LPARAM)pStr)
== iPosDst) {
// Attempt to sync up the actual toolbar.
if (wIDDst == IDC_CURRENT) {
if (LOWORD(dwTemp) == 0xffff) {
// Make up a dummy lpInfo if this is a space
aiTemp.tbButton.iBitmap = 0;
aiTemp.tbButton.fsStyle = TBSTYLE_SEP;
lpInfo = (LPADJUSTINFO)&aiTemp;
} else {
// Ask the app for the info
hInfo = (HANDLE)(int)SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,HIWORD(dwTemp)&~(FLAG_ALLFLAGS),TBN_ADJUSTINFO));
if (!hInfo)
goto DelTheDst;
lpInfo = (LPADJUSTINFO) hInfo;
}
if (!SendMessage(hwndToolbar, TB_INSERTBUTTON, iPosDst,
(LPARAM)&(lpInfo->tbButton))) {
DelTheDst:
SendMessage(hwndDst, LB_DELETESTRING, iPosDst, 0L);
goto CleanUp;
}
if (wIDSrc==IDC_CURRENT && iPosSrc>=iPosDst)
++iPosSrc;
}
SendMessage(hwndDst, LB_SETITEMDATA, iPosDst, dwTemp);
DelTheSrc:
// Don't delete the "Separator" in the new list
if (wIDSrc!=IDC_BUTTONLIST || iPosSrc!=0) {
SendMessage(hwndSrc, LB_DELETESTRING, iPosSrc, 0L);
if (wIDSrc == wIDDst) {
if (iPosSrc < iPosDst)
--iPosDst;
if (iPosSrc < iTopDst)
--iTopDst;
}
}
// Delete the corresponding button
if (wIDSrc == IDC_CURRENT)
SendMessage(hwndToolbar, TB_DELETEBUTTON, iPosSrc, 0L);
// Only set the src index if the two windows are different
if (wIDSrc != wIDDst) {
if (SendMessage(hwndSrc, LB_SETCURSEL, iPosSrc, 0L) == LB_ERR)
SendMessage(hwndSrc, LB_SETCURSEL, iPosSrc-1, 0L);
SendMessage(hDlg, WM_COMMAND,
GET_WM_COMMAND_MPS(wIDSrc,hwndSrc, LBN_SELCHANGE));
}
// Send the final SELCHANGE message after everything else is done
SendMessage(hwndDst, LB_SETCURSEL, iPosDst+iSelOffset, 0L);
SendMessage(hDlg, WM_COMMAND,
GET_WM_COMMAND_MPS(wIDDst, hwndDst, LBN_SELCHANGE));
}
// Cleanup moved down 1 line from curly
CleanUp:
LocalFree((HLOCAL)pStr);
if (wIDSrc == wIDDst)
SendMessage(hwndDst, LB_SETTOPINDEX, iTopDst, 0L);
SendMessage(hwndDst, WM_SETREDRAW, 1, 0L);
InvalidateRect(hwndDst, NULL, TRUE);
}
Static VOID
SafeEnableWindow(HWND hDlg, UINT uiID, HWND hwndDef,
BOOL bEnable)
{
HWND hwndEnable;
hwndEnable = GetDlgItem(hDlg, uiID);
if (!bEnable && GetFocus()==hwndEnable)
SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hwndDef, 1L);
EnableWindow(hwndEnable, bEnable);
}
Static VOID
GetTBStuff(HWND hDlg, LPTBSTUFF pTBStuff)
{
LPADJUSTDLGDATA lpad;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
pTBStuff->hwndToolbar = lpad->hwndToolbar;
pTBStuff->pTBState = (PTBSTATE)GetWindowLong(pTBStuff->hwndToolbar,
GWL_PTBSTATE);
}
Static INT
InsertIndex(HWND hDlg, POINT pt, BOOL bDragging)
{
HWND hwndCurrent;
INT nItem;
TBSTUFF TBStuff;
hwndCurrent = GetDlgItem(hDlg, IDC_CURRENT);
nItem = LBItemFromPt(hwndCurrent, pt, bDragging);
if (nItem >= 0) {
GetTBStuff(hDlg, &TBStuff);
if (!SendMessage(TBStuff.pTBState->hwndCommand, WM_COMMAND,
GET_WM_COMMAND_MPS(GetDlgCtrlID(TBStuff.hwndToolbar),
nItem, TBN_QUERYINSERT)))
nItem = -1;
}
DrawInsert(hDlg, hwndCurrent, bDragging ? nItem : -1);
return(nItem);
}
Static BOOL
IsInButtonList(HWND hDlg, POINT pt)
{
ScreenToClient(hDlg, &pt);
return(ChildWindowFromPoint(hDlg, pt) == GetDlgItem(hDlg, IDC_BUTTONLIST));
}
Static BOOL
HandleDragMsg(HWND hDlg, WPARAM wID, LPDRAGLISTINFO lpns)
{
switch (wID) {
case IDC_CURRENT:
switch (lpns->uNotification) {
case DL_BEGINDRAG:
{
int nItem;
nItem = (int)SendMessage(lpns->hWnd, LB_GETCURSEL,0,0L);
if (HIWORD(SendMessage(lpns->hWnd, LB_GETITEMDATA,
nItem, 0L)) & FLAG_NODEL)
return(SetDlgMsgResult(hDlg, WM_COMMAND, FALSE));
return(SetDlgMsgResult(hDlg, WM_COMMAND, TRUE));
}
case DL_DRAGGING:
{
int nDropIndex;
DraggingSomething:
nDropIndex = InsertIndex(hDlg, lpns->ptCursor, TRUE);
if (nDropIndex>=0 || IsInButtonList(hDlg, lpns->ptCursor)) {
SetCursor(LoadCursor(hInst,
(LPTSTR) MAKEINTRESOURCE(IDC_MOVEBUTTON)));
return(SetDlgMsgResult(hDlg, WM_COMMAND, 0));
}
return(SetDlgMsgResult(hDlg, WM_COMMAND, DL_STOPCURSOR));
}
case DL_DROPPED:
{
int nDropIndex, nSrcIndex;
nDropIndex = InsertIndex(hDlg, lpns->ptCursor, FALSE);
nSrcIndex = (int)SendMessage(lpns->hWnd, LB_GETCURSEL, 0, 0L);
if (nDropIndex >= 0) {
if ((UINT)(nDropIndex-nSrcIndex) > 1)
LBMoveButton(hDlg, IDC_CURRENT, nSrcIndex,
IDC_CURRENT, nDropIndex, 0);
} else if (IsInButtonList(hDlg, lpns->ptCursor)) {
LBMoveButton(hDlg, IDC_CURRENT, nSrcIndex,
IDC_BUTTONLIST, 0, 0);
}
break;
}
case DL_CANCELDRAG:
CancelDrag:
/* This erases the insert icon if it exists.
*/
InsertIndex(hDlg, lpns->ptCursor, FALSE);
break;
default:
break;
}
break;
case IDC_BUTTONLIST:
switch (lpns->uNotification) {
case DL_BEGINDRAG:
return(SetDlgMsgResult(hDlg, WM_COMMAND, TRUE));
case DL_DRAGGING:
goto DraggingSomething;
case DL_DROPPED:
{
int nDropIndex;
nDropIndex = InsertIndex(hDlg, lpns->ptCursor, FALSE);
if (nDropIndex >= 0)
LBMoveButton(hDlg, IDC_BUTTONLIST,
(int)SendMessage(lpns->hWnd,LB_GETCURSEL,0,0L),
IDC_CURRENT, nDropIndex, 0);
break;
}
case DL_CANCELDRAG:
goto CancelDrag;
default:
break;
}
break;
default:
break;
}
return(0);
}
BOOL CALLBACK
AdjustDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
{
HWND hwndCurrent;
SetWindowLong(hDlg, GWL_USERDATA, lParam); /* LPADJUSTDLGDATA pointer */
if (!InitAdjustDlg(hDlg, ((LPADJUSTDLGDATA)lParam)->hwndToolbar,
((LPADJUSTDLGDATA)lParam)->iPos))
EndDialog(hDlg, FALSE);
hwndCurrent = GetDlgItem(hDlg, IDC_CURRENT);
ShowWindow(hDlg, SW_SHOW);
UpdateWindow(hDlg);
SetFocus(hwndCurrent);
MakeDragList(hwndCurrent);
MakeDragList(GetDlgItem(hDlg, IDC_BUTTONLIST));
return(FALSE);
}
case WM_MEASUREITEM:
#define lpmis ((MEASUREITEMSTRUCT FAR *)lParam)
if (lpmis->CtlID==IDC_BUTTONLIST || lpmis->CtlID==IDC_CURRENT) {
HWND hwndList;
HDC hDC;
SIZE Size;
int nHeight;
hwndList = GetDlgItem(hDlg, lpmis->CtlID);
hDC = GetDC(hwndList);
GetTextExtentPoint(hDC, szSampleText, COUNTOF(szSampleText)-1,&Size);
nHeight = Size.cy;
if (nHeight < dyButton+2)
nHeight = dyButton+2;
lpmis->itemHeight = nHeight;
ReleaseDC(hwndList, hDC);
break;
}
case WM_DRAWITEM:
PaintAdjustLine((DRAWITEMSTRUCT FAR *)lParam,
((LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA))->hwndToolbar);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam,lParam)) {
case IDC_HELP:
{
HWND hwndParent, hwndToolbar;
PTBSTATE pTBState;
LPADJUSTDLGDATA lpad;
WORD wID;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
hwndToolbar = lpad->hwndToolbar;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
wID = (WORD)GetWindowLong(hwndToolbar, GWL_ID);
hwndParent = pTBState->hwndCommand;
SendMessage(hwndParent, WM_COMMAND, GET_WM_COMMAND_MPS(wID,hDlg, TBN_CUSTHELP));
break;
}
case IDOK:
{
int iPos, nItem;
nItem = (int)SendDlgItemMessage(hDlg, IDC_BUTTONLIST,
LB_GETCURSEL, 0, 0L);
iPos = (int)SendDlgItemMessage(hDlg, IDC_CURRENT,
LB_GETCURSEL, 0, 0L);
LBMoveButton(hDlg, IDC_BUTTONLIST, nItem, IDC_CURRENT, iPos, 1);
break;
}
case IDC_BUTTONLIST:
switch (GET_WM_COMMAND_CMD(wParam,lParam)) {
case LBN_DBLCLK:
SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(IDOK, 0, 0L));
break;
case LBN_SETFOCUS:
case LBN_KILLFOCUS:
{
RECT rc;
if (SendMessage((HWND) lParam, LB_GETITEMRECT,
(int)SendMessage((HWND) lParam, LB_GETCURSEL,
0, 0L), (LONG)(LPRECT)&rc) != LB_ERR)
InvalidateRect((HWND) lParam, &rc, FALSE);
}
default:
break;
}
break;
case IDC_CURRENT:
switch (GET_WM_COMMAND_CMD(wParam,lParam)) {
case LBN_SELCHANGE:
{
HWND hwndParent, hwndToolbar, hwndList;
PTBSTATE pTBState;
int iPos;
LPADJUSTDLGDATA lpad;
UINT uiID;
BOOL bDelOK;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
hwndToolbar = lpad->hwndToolbar;
hwndList = (HWND) lParam;
iPos = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
uiID = GetWindowLong(hwndToolbar, GWL_ID);
hwndParent = pTBState->hwndCommand;
SafeEnableWindow(hDlg, IDOK, hwndList,
(BOOL)SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,iPos, TBN_QUERYINSERT)));
bDelOK = !(HIWORD(SendMessage((HWND)lParam,
LB_GETITEMDATA, iPos, 0L)) & FLAG_NODEL);
SafeEnableWindow(hDlg, IDC_REMOVE, hwndList, bDelOK);
SafeEnableWindow(hDlg, IDC_MOVEUP, hwndList, bDelOK &&
GetNearestInsert(hwndParent, uiID, iPos-1,
0, GNI_LOW)>=0);
SafeEnableWindow(hDlg, IDC_MOVEDOWN, hwndList, bDelOK &&
GetNearestInsert(hwndParent, uiID, iPos+2,
pTBState->iNumButtons, GNI_HIGH)>=0);
break;
}
case LBN_DBLCLK:
SendMessage(hDlg, WM_COMMAND,
GET_WM_COMMAND_MPS(IDC_REMOVE, 0L, 0));
break;
case LBN_SETFOCUS:
case LBN_KILLFOCUS:
{
RECT rc;
if (SendMessage((HWND) lParam, LB_GETITEMRECT,
(int)SendMessage((HWND) lParam, LB_GETCURSEL,
0, 0L), (LONG)(LPRECT)&rc) != LB_ERR)
InvalidateRect((HWND) lParam, &rc, FALSE);
}
default:
break;
}
break;
case IDC_REMOVE:
{
int iPos;
iPos = (int)SendDlgItemMessage(hDlg, IDC_CURRENT, LB_GETCURSEL,
0, 0L);
LBMoveButton(hDlg, IDC_CURRENT, iPos, IDC_BUTTONLIST, 0, 0);
break;
}
case IDC_MOVEUP:
case IDC_MOVEDOWN:
{
LPADJUSTDLGDATA lpad;
HWND hwndToolbar, hwndParent;
PTBSTATE pTBState;
UINT uiID;
int iPosSrc, iPosDst;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
hwndToolbar = lpad->hwndToolbar;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
hwndParent = pTBState->hwndCommand;
uiID = GetWindowLong(hwndToolbar, GWL_ID);
iPosSrc = (int)SendDlgItemMessage(hDlg, IDC_CURRENT,
LB_GETCURSEL, 0, 0L);
if (GET_WM_COMMAND_ID(wParam,lParam) == IDC_MOVEUP)
iPosDst = GetNearestInsert(hwndParent, uiID, iPosSrc-1,
0, GNI_LOW);
else
iPosDst = GetNearestInsert(hwndParent, uiID, iPosSrc+2,
pTBState->iNumButtons, GNI_HIGH);
LBMoveButton(hDlg, IDC_CURRENT, iPosSrc, IDC_CURRENT,iPosDst,0);
break;
}
case IDC_RESET:
{
HWND hwndToolbar;
PTBSTATE pTBState;
LPADJUSTDLGDATA lpad;
lpad = (LPADJUSTDLGDATA)GetWindowLong(hDlg, GWL_USERDATA);
hwndToolbar = lpad->hwndToolbar;
pTBState = (PTBSTATE)GetWindowLong(hwndToolbar, GWL_PTBSTATE);
SendMessage(pTBState->hwndCommand, WM_COMMAND,
GET_WM_COMMAND_MPS(GetWindowLong(hwndToolbar, GWL_ID),
0, TBN_RESET));
// Reset the dialog, but exit if something goes wrong.
if (InitAdjustDlg(hDlg, hwndToolbar, 0))
break;
}
// We have to fall through because we won't know where to insert
// buttons after resetting.
case IDCANCEL:
EndDialog(hDlg, TRUE);
break;
default:
return(FALSE);
}
break;
default:
if (uMsg == uDragListMsg)
return(HandleDragMsg(hDlg, wParam, (LPDRAGLISTINFO)lParam));
return(FALSE);
}
return(TRUE);
}
/* This saves the state of the toolbar. Spaces are saved as -1 (-2 if hidden)
* and other buttons are just saved as the command ID. When restoring, all
* ID's are filled in, and the app is queried for all buttons so that the
* bitmap and state information may be filled in. Button ID's that are not
* returned from the app are removed.
*/
BOOL FAR PASCAL SaveRestore(HWND hWnd, PTBSTATE pTBState, BOOL bWrite,
LPTSTR FAR *lpNames)
{
HWND hwndParent;
int *pInt, iPos, i;
BOOL bRet;
WORD wSize;
UINT uiID;
HANDLE hInfo;
LPADJUSTINFO lpInfo;
PTBBUTTON ptbButton;
PTBSTATE pTemp;
if (bWrite)
{
i = pTBState->iNumButtons;
/* The + 1 in the alloc is just in case there are no buttons
*/
wSize = (WORD)(i * sizeof(int));
pInt = (int *)LocalAlloc(LMEM_FIXED, wSize + 1);
if (!pInt)
return(FALSE);
bRet = WritePrivateProfileStruct(lpNames[0], szNumButtons,
(LPBYTE)&i, sizeof(i), lpNames[1]);
pInt += i;
ptbButton = pTBState->Buttons + i;
for (--i; i>=0; --i)
{
--pInt;
--ptbButton;
if (ptbButton->fsStyle & TBSTYLE_SEP)
{
if (ptbButton->fsState & TBSTATE_HIDDEN)
*pInt = -2;
else
*pInt = -1;
}
else
*pInt = ptbButton->idCommand;
}
bRet = bRet && WritePrivateProfileStruct(lpNames[0], (LPTSTR)szToolbarClass,
(LPBYTE)pInt, wSize, lpNames[1]);
}
else
{
bRet = GetPrivateProfileStruct(lpNames[0], (LPTSTR)szNumButtons,
(LPBYTE)&i, sizeof(i), lpNames[1]);
wSize = (WORD)(i * sizeof(int));
if (!bRet || (pInt=(int *)LocalAlloc(LMEM_FIXED, wSize + 1)) == NULL)
return(FALSE);
bRet = GetPrivateProfileStruct(lpNames[0], (LPTSTR)szToolbarClass,
(LPBYTE)pInt, wSize, lpNames[1]);
if (bRet) {
pTemp = (PTBSTATE)LocalReAlloc(pTBState,
sizeof(TBSTATE) + (i - 1) * sizeof(TBBUTTON), LMEM_MOVEABLE);
if (!pTemp)
goto Error1;
pTBState = pTemp;
SetWindowLong(hWnd, GWL_PTBSTATE, (LONG)pTBState);
pTBState->iNumButtons = i;
pInt += i;
ptbButton = pTBState->Buttons + i;
for (--i; i>=0; --i)
{
--pInt;
--ptbButton;
if (*pInt < 0)
{
ptbButton->fsStyle = TBSTYLE_SEP;
ptbButton->iBitmap = dxButtonSep;
if (*pInt == -1)
ptbButton->fsState = 0;
else
ptbButton->fsState = TBSTATE_HIDDEN;
}
else
{
ptbButton->idCommand = *pInt;
ptbButton->iBitmap = -1;
}
}
/* Now query for all buttons, and fill in the rest of the info
*/
uiID = GetWindowLong(hWnd, GWL_ID);
hwndParent = pTBState->hwndCommand;
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,0, TBN_BEGINADJUST));
for (i=0; ; ++i)
{
hInfo = (HANDLE)(int)SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, i, TBN_ADJUSTINFO));
if (!hInfo)
break;
lpInfo = (LPADJUSTINFO) hInfo;
if (!(lpInfo->tbButton.fsStyle&TBSTYLE_SEP))
{
iPos = PositionFromID(pTBState, lpInfo->tbButton.idCommand);
if (iPos >= 0)
pTBState->Buttons[iPos] = lpInfo->tbButton;
}
}
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID,0, TBN_ENDADJUST));
for (i=pTBState->iNumButtons-1; i>=0; --i)
{
/* DeleteButton does no realloc, so pTBState will not move
*/
if (pTBState->Buttons[i].iBitmap < 0)
SendMessage(hWnd, TB_DELETEBUTTON, i, 0L);
}
}
}
Error1:
LocalFree((HLOCAL)pInt);
return(bRet);
}
void FAR PASCAL CustomizeTB(HWND hWnd, PTBSTATE pTBState, int iPos)
{
UINT uiID = GetWindowLong(hWnd, GWL_ID);
ADJUSTDLGDATA ad;
HWND hwndParent;
if (pTBState->hdlgCust) /* We are already customizing this toolbar */
return;
hwndParent = pTBState->hwndCommand;
ad.hwndToolbar = hWnd;
ad.iPos = iPos;
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, 0, TBN_BEGINADJUST));
DialogBoxParam(hInst, (LPTSTR) MAKEINTRESOURCE(ADJUSTDLG), hwndParent,
(DLGPROC)AdjustDlgProc, (LPARAM)(LPADJUSTDLGDATA)&ad);
pTBState = (PTBSTATE)GetWindowLong(hWnd, GWL_PTBSTATE);
pTBState->hdlgCust = NULL;
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, 0, TBN_ENDADJUST));
SendMessage(hwndParent, WM_COMMAND,
GET_WM_COMMAND_MPS(uiID, hWnd, TBN_TOOLBARCHANGE));
}