mirror of https://github.com/lianthony/NT4.0
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.
661 lines
18 KiB
661 lines
18 KiB
// UI.CPP
|
|
|
|
#include "common.h"
|
|
|
|
#define mskTraceLocalDebug 0x00000
|
|
|
|
CStatusBar StatusBar;
|
|
|
|
HMENU hmenuMain; // Menu handle of the main window
|
|
HMENU hmenuContext; // Context menu handle
|
|
|
|
HCURSOR hcursorArrow; // Standard Arrow Cursor
|
|
HCURSOR hcursorWait; // Hourglass cursor
|
|
HCURSOR hcursorNo; // Slashed circle cursor
|
|
HCURSOR hcursorSplit; // Split window cursor
|
|
HCURSOR hcursorFinger;
|
|
HCURSOR hcursorFingerNo;
|
|
|
|
HFONT hfontNormal; // Normal dialog font
|
|
HFONT hfontBold; // Bold dialog font
|
|
HFONT hfontBig; // 3/2 dialog font
|
|
|
|
COLORREF clrWindow;
|
|
COLORREF clrWindowText;
|
|
COLORREF clrHighlight;
|
|
COLORREF clrHighlightText;
|
|
|
|
HBRUSH hbrWindow;
|
|
HBRUSH hbrWindowText;
|
|
HBRUSH hbrHighlight;
|
|
|
|
int cyCharListBoxItem = 13; // Height of a listbox item
|
|
int cyCharStaticCtrl = 13; // Height of a single line static control
|
|
|
|
SPLITTERINFO splitterinfo = { NULL, SPI_nDragModeNone, 60, 0 };
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL FInitBrushes()
|
|
{
|
|
hcursorArrow = LoadCursor(NULL, IDC_ARROW);
|
|
hcursorWait = LoadCursor(NULL, IDC_WAIT);
|
|
hcursorNo = LoadCursor(NULL, IDC_NO);
|
|
hcursorSplit = HLoadCursor(ID_CURSOR_VSPLIT);
|
|
hcursorFinger = HLoadCursor(ID_CURSOR_FINGER);
|
|
hcursorFingerNo = HLoadCursor(ID_CURSOR_FINGERNO);
|
|
|
|
clrWindow = GetSysColor(COLOR_WINDOW);
|
|
clrWindowText = GetSysColor(COLOR_WINDOWTEXT);
|
|
clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
|
|
clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
|
|
hbrWindow = CreateSolidBrush(clrWindow);
|
|
Report(hbrWindow);
|
|
hbrWindowText = CreateSolidBrush(clrWindowText);
|
|
Report(hbrWindowText);
|
|
hbrHighlight = CreateSolidBrush(clrHighlight);
|
|
Report(hbrHighlight);
|
|
|
|
return (hbrWindow && hbrWindowText && hbrHighlight);
|
|
} // FInitBrushes
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void DestroyBrushes()
|
|
{
|
|
SideReport(DeleteObject(hbrWindow));
|
|
SideReport(DeleteObject(hbrWindowText));
|
|
SideReport(DeleteObject(hbrHighlight));
|
|
} // DestroyBrushes
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void MoveSplitterWindow()
|
|
{
|
|
int xSplitterT;
|
|
|
|
xSplitterT = splitterinfo.xOffset + (mainwindowposition.cx / 4);
|
|
if (xSplitterT < 60)
|
|
xSplitterT = 60;
|
|
if (xSplitterT > mainwindowposition.cx - 60)
|
|
xSplitterT = mainwindowposition.cx - 60;
|
|
|
|
splitterinfo.xPosLast = xSplitterT;
|
|
HDWP hdwp = BeginDeferWindowPos(3);
|
|
hdwp = DeferWindowPos(hdwp, TreeView.m_hWnd, NULL,
|
|
0, 0,
|
|
xSplitterT, mainwindowposition.cy - 1,
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
|
|
Report(hdwp);
|
|
hdwp = DeferWindowPos(hdwp, splitterinfo.hwnd, NULL,
|
|
xSplitterT, 0,
|
|
4, mainwindowposition.cy,
|
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS);
|
|
Report(hdwp);
|
|
xSplitterT += 4;
|
|
hdwp = HelperMgr.HDeferWindowPos(
|
|
hdwp,
|
|
xSplitterT, 0,
|
|
mainwindowposition.cx - xSplitterT, mainwindowposition.cy - 1);
|
|
SideReport(EndDeferWindowPos(hdwp));
|
|
} // MoveSplitterWindow
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
LRESULT CALLBACK WndProcSplitter(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
RECT rc;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_ERASEBKGND:
|
|
GetClientRect(hwnd, OUT &rc);
|
|
SelectObject((HDC)wParam, GetStockObject(WHITE_PEN));
|
|
MoveToEx((HDC)wParam, 0, rc.bottom, NULL);
|
|
LineTo((HDC)wParam, 0, 0);
|
|
rc.left = 1;
|
|
FillRect((HDC)wParam, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
|
|
LineTo((HDC)wParam, rc.right, 0);
|
|
return TRUE;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
splitterinfo.nDragMode = SPI_nDragModeMouse;
|
|
SetCapture(hwnd);
|
|
return 0;
|
|
|
|
case WM_LBUTTONUP:
|
|
splitterinfo.nDragMode = SPI_nDragModeNone;
|
|
ReleaseCapture();
|
|
SetFocus(hwndMain);
|
|
return 0;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (splitterinfo.nDragMode)
|
|
{
|
|
splitterinfo.xOffset = (signed short)LOWORD(lParam) - 1 + splitterinfo.xPosLast
|
|
- (mainwindowposition.cx / 4);
|
|
MoveSplitterWindow();
|
|
SetCapture(hwnd);
|
|
}
|
|
return 0;
|
|
|
|
case WM_SETFOCUS:
|
|
splitterinfo.nDragMode = SPI_nDragModeKeyboard;
|
|
GetWindowRect(hwnd, OUT &rc);
|
|
SetCursorPos(rc.left + 1, rc.top + (rc.bottom - rc.top) / 5);
|
|
StatusBar.SetText(IDS_STATUS_MOVE_SPLIT_BAR);
|
|
return 0;;
|
|
|
|
case WM_KILLFOCUS:
|
|
splitterinfo.nDragMode = SPI_nDragModeNone;
|
|
ReleaseCapture();
|
|
StatusBar.SetText(IDS_READY);
|
|
return 0;
|
|
|
|
case WM_KEYDOWN:
|
|
Report(splitterinfo.nDragMode != SPI_nDragModeNone);
|
|
splitterinfo.nDragMode = SPI_nDragModeKeyboard;
|
|
ReleaseCapture();
|
|
lParam = 1;
|
|
switch (wParam)
|
|
{
|
|
case VK_LEFT:
|
|
splitterinfo.xOffset -= 5;
|
|
MoveSplitterWindow();
|
|
break;
|
|
case VK_RIGHT:
|
|
splitterinfo.xOffset += 5;
|
|
MoveSplitterWindow();
|
|
break;
|
|
case VK_ESCAPE:
|
|
case VK_RETURN:
|
|
lParam = -4;
|
|
SetFocus(hwndMain);
|
|
}
|
|
GetWindowRect(hwnd, OUT &rc);
|
|
SetCursorPos(rc.left + lParam, rc.top + (rc.bottom - rc.top) / 5);
|
|
return 0;
|
|
|
|
} // switch
|
|
|
|
return DefWindowProc (hwnd, uMsg, wParam, lParam);
|
|
} // WndProcSplitter
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CWaitCursor::CWaitCursor(HWND hwnd)
|
|
{
|
|
Assert(IsWindow(hwnd));
|
|
Assert(hcursorWait);
|
|
m_hCursorPrev = SetCursor(hcursorWait);
|
|
SetCapture(hwnd);
|
|
} // CWaitCursor
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CWaitCursor::~CWaitCursor()
|
|
{
|
|
SetCursor(m_hCursorPrev);
|
|
ReleaseCapture();
|
|
} // ~CWaitCursor
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CWaitTimer::CWaitTimer()
|
|
{
|
|
m_dwInitTime = GetTickCount();
|
|
} // CWaitTimer
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CWaitTimer::DoWait(LONG lMaximumSleepTime)
|
|
{
|
|
LONG l;
|
|
|
|
l = GetTickCount() - m_dwInitTime;
|
|
Report(l >= 0);
|
|
lMaximumSleepTime -= l;
|
|
Report(lMaximumSleepTime < 60000);
|
|
Trace1(mskTracePaintUI, "\nCWaitTimer::DoWait() - Sleeping for %d milliseconds...", lMaximumSleepTime);
|
|
if (lMaximumSleepTime > 0)
|
|
Sleep(lMaximumSleepTime & 0xFFFF);
|
|
} // DoWait
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CStatusBar::FCreate()
|
|
{
|
|
RECT rc;
|
|
|
|
// Create the status bar
|
|
Assert(m_hWnd == NULL);
|
|
Assert(IsWindow(hwndMain));
|
|
m_hWnd = CreateWindow(
|
|
STATUSCLASSNAME,
|
|
NULL, // Pane 0 text
|
|
WS_CHILD | WS_VISIBLE, // Style of the status bar bits
|
|
0, 0, 0, 0, // The size of the status bar is handled by WM_SIZE
|
|
hwndMain, // Parent windowh
|
|
(HMENU)ID_STATUSBAR, // StatusBar ID
|
|
hInstanceSave, // Instance handle
|
|
NULL); // No parameters
|
|
Report(m_hWnd);
|
|
if (!m_hWnd)
|
|
return FALSE;
|
|
GetWindowRect(m_hWnd, &rc);
|
|
m_cy = rc.bottom - rc.top;
|
|
return TRUE;
|
|
} // CStatusBar::FCreate
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetText(UINT wIdString)
|
|
{
|
|
TCHAR szT[256];
|
|
|
|
Assert(HIWORD(wIdString) == 0);
|
|
CchLoadString(wIdString, szT, LENGTH(szT));
|
|
Assert(IsWindow(m_hWnd));
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 0 /* Pane 0 */, (LPARAM)szT);
|
|
} // SetText
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetText(const TCHAR szText[])
|
|
{
|
|
Assert(IsWindow(m_hWnd));
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 0 /* Pane 0 */, (LPARAM)szText);
|
|
} // SetText
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetTextPrintf(const TCHAR szTextFmt[], ...)
|
|
{
|
|
TCHAR szBuffer[512]; // Buffer to hold the final result
|
|
va_list arglist;
|
|
|
|
va_start(arglist, szTextFmt);
|
|
wvsprintf(szBuffer, szTextFmt, arglist);
|
|
Assert(lstrlen(szBuffer) < LENGTH(szBuffer));
|
|
Assert(IsWindow(m_hWnd));
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 0 /* Pane 0 */, (LPARAM)szBuffer);
|
|
} // SetTextPrintf
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetTextPrintf(UINT wIdString, ...)
|
|
{
|
|
TCHAR szFormat[256]; // Format of the string
|
|
TCHAR szBuffer[512]; // Buffer to hold the final result
|
|
va_list arglist;
|
|
|
|
va_start(arglist, wIdString);
|
|
CchLoadString(wIdString, szFormat, LENGTH(szFormat));
|
|
wvsprintf(szBuffer, szFormat, arglist);
|
|
Assert(lstrlen(szBuffer) < LENGTH(szBuffer));
|
|
Assert(IsWindow(m_hWnd));
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 0 /* Pane 0 */, (LPARAM)szBuffer);
|
|
} // SetTextPrintf
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetPaneText(UINT wIdString)
|
|
{
|
|
TCHAR szT[128];
|
|
|
|
Assert(HIWORD(wIdString) == 0);
|
|
CchLoadString(wIdString, szT, LENGTH(szT));
|
|
Assert(IsWindow(m_hWnd));
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 1 /* Pane 1 */, (LPARAM)szT);
|
|
} // CStatusBar::SetPaneText
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::SetPaneText(const TCHAR szText[])
|
|
{
|
|
Assert(IsWindow(m_hWnd));
|
|
Assert(szText);
|
|
LSendMessage(m_hWnd, SB_SETTEXT, 1 /* Pane 1 */, (LPARAM)szText);
|
|
} // CStatusBar::SetPaneText
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CStatusBar::OnSize(int cx)
|
|
{
|
|
int rgPaneWidth[2] = { cx - (70 + cx/10), -1 };
|
|
LSendMessage(m_hWnd, SB_SETPARTS, 2, (LPARAM)rgPaneWidth);
|
|
LSendMessage(m_hWnd, WM_SIZE, 0, 0);
|
|
} // CStatusBar::OnSize
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CWndHeader::FInit(
|
|
HWND hwndHeader,
|
|
HWND hwndListBox,
|
|
HEADERITEMINFO rgHeaderItem[],
|
|
int cHeaderItem)
|
|
{
|
|
HD_ITEM hdi; // Header item
|
|
TCHAR szT[64];
|
|
int i, j;
|
|
|
|
AssertClassName(hwndHeader, WC_HEADER);
|
|
Assert(IsWindow(hwndListBox));
|
|
Assert(rgHeaderItem);
|
|
|
|
m_hWnd = hwndHeader;
|
|
m_hwndListBox = hwndListBox;
|
|
m_rgHeaderItem = rgHeaderItem;
|
|
m_cHeaderItem = cHeaderItem;
|
|
m_iAutoFitItem = -1;
|
|
|
|
Report(GetWindowLong(hwndListBox, GWL_USERDATA) == 0);
|
|
SetWindowLong(hwndListBox, GWL_USERDATA, (LONG)rgHeaderItem);
|
|
|
|
hdi.mask = HDI_FORMAT | HDI_WIDTH | HDI_TEXT;
|
|
hdi.fmt = HDF_LEFT | HDF_STRING;
|
|
hdi.pszText = szT;
|
|
for (i = 0; i < cHeaderItem; i++)
|
|
{
|
|
hdi.cxy = rgHeaderItem[i].cxItemInitial;
|
|
if (hdi.cxy == 0)
|
|
{
|
|
Trace0(m_iAutoFitItem >= 0 ? mskTraceAlways : mskTraceNone,
|
|
"\nOnly one item can be auto sized.");
|
|
m_iAutoFitItem = i;
|
|
}
|
|
CchLoadString(rgHeaderItem[i].idsItem, szT, LENGTH(szT));
|
|
j = Header_InsertItem(hwndHeader, i, &hdi);
|
|
Report(j == i);
|
|
} // for
|
|
// Add one last item for better UI
|
|
hdi.pszText = (TCHAR *)szNull;
|
|
Header_InsertItem(hwndHeader, i, &hdi);
|
|
m_cyWnd = 0;
|
|
DoLayout();
|
|
} // CWndHeader::FInit
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CWndHeader::SetSize(int cx, int cyListBox)
|
|
{
|
|
Assert(IsWindow(m_hWnd));
|
|
HDWP hdwp = BeginDeferWindowPos(2);
|
|
Report(hdwp != NULL);
|
|
if (m_cyWnd == 0)
|
|
{
|
|
RECT rc;
|
|
|
|
GetWindowRect(m_hWnd, OUT &rc);
|
|
m_cyWnd = rc.bottom - rc.top;
|
|
GetWindowRect(m_hwndListBox, OUT &rc);
|
|
Assert(IsWindow(GetParent(m_hwndListBox)));
|
|
MapWindowPoints(HWND_DESKTOP, GetParent(m_hwndListBox), INOUT (POINT*)&rc, 2);
|
|
hdwp = DeferWindowPos(
|
|
hdwp, m_hWnd, NULL,
|
|
rc.left, rc.top - m_cyWnd + 4, cx, m_cyWnd,
|
|
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOZORDER);
|
|
}
|
|
else
|
|
{
|
|
hdwp = DeferWindowPos(
|
|
hdwp, m_hWnd, NULL,
|
|
0, 0, cx, m_cyWnd,
|
|
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
Report(hdwp != NULL);
|
|
hdwp = DeferWindowPos(
|
|
hdwp, m_hwndListBox, NULL,
|
|
0, 0, cx, cyListBox,
|
|
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
|
Report(hdwp != NULL);
|
|
SideReport(EndDeferWindowPos(hdwp));
|
|
DoLayout();
|
|
} // CWndHeader::SetSize
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DoLayout()
|
|
//
|
|
// Layout the widths of each columns
|
|
//
|
|
void CWndHeader::DoLayout()
|
|
{
|
|
HD_ITEM hdi; // Header item
|
|
RECT rc;
|
|
int i;
|
|
int x;
|
|
|
|
GetClientRect(m_hwndListBox, OUT &rc);
|
|
Assert(rc.left == 0);
|
|
m_cyWndListBox = rc.bottom;
|
|
GetClientRect(m_hWnd, OUT &rc);
|
|
Assert(rc.left == 0);
|
|
m_cxWnd = rc.right;
|
|
|
|
x = 0;
|
|
hdi.mask = HDI_WIDTH;
|
|
for (i = 0; i < m_cHeaderItem; i++)
|
|
{
|
|
SideReport(Header_GetItem(m_hWnd, i, OUT &hdi));
|
|
m_rgHeaderItem[i].cxItemCurrent = hdi.cxy;
|
|
if (i != m_iAutoFitItem)
|
|
x += hdi.cxy;
|
|
}
|
|
if (m_iAutoFitItem >= 0)
|
|
{
|
|
int cxAuto = m_cxWnd - x;
|
|
Trace0(cxAuto > 0 ? mskTraceNone : mskTracePaintUI,
|
|
"\nUI: INFO: Width of control too small to for autofit");
|
|
m_rgHeaderItem[m_iAutoFitItem].cxItemCurrent = cxAuto;
|
|
// Change the width of the item
|
|
hdi.cxy = cxAuto;
|
|
SideReport(Header_SetItem(m_hWnd, m_iAutoFitItem, IN &hdi));
|
|
}
|
|
Report((HEADERITEMINFO *)GetWindowLong(m_hwndListBox, GWL_USERDATA) == m_rgHeaderItem);
|
|
//SetWindowPos(
|
|
// m_hwndListBox, NULL,
|
|
// 0, 0, 0, 0,
|
|
// SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
|
|
} // CWndHeader::DoLayout
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CWndHeader::DrawListBoxLine()
|
|
{
|
|
HDC hdcListBox;
|
|
|
|
Assert(IsWindow(m_hwndListBox));
|
|
hdcListBox = GetDC(m_hwndListBox);
|
|
SetROP2(hdcListBox, R2_NOT);
|
|
MoveToEx(hdcListBox, m_xDragStart + m_cxDragCurrent, 0, NULL);
|
|
LineTo(hdcListBox, m_xDragStart + m_cxDragCurrent, m_cyWndListBox);
|
|
ReleaseDC(m_hwndListBox, hdcListBox);
|
|
} // CWndHeader::DrawListBoxLine
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CWndHeader::FOnNotify(HD_NOTIFY * pHeaderNotify)
|
|
{
|
|
HD_ITEM hdi;
|
|
int i;
|
|
int x;
|
|
|
|
Assert(pHeaderNotify != NULL);
|
|
Assert(pHeaderNotify->hdr.hwndFrom == m_hWnd);
|
|
|
|
switch (pHeaderNotify->hdr.code)
|
|
{
|
|
case HDN_BEGINTRACK:
|
|
Assert(pHeaderNotify->pitem != NULL);
|
|
// Compute the maximum and minimum width of item
|
|
if (pHeaderNotify->iItem >= m_cHeaderItem - 1)
|
|
{
|
|
Trace0(mskTraceLocalDebug, "\nHDN_BEGINTRACK: NoDrag");
|
|
break;
|
|
}
|
|
Assert(pHeaderNotify->iItem >= 0);
|
|
m_cxDragCurrent = pHeaderNotify->pitem->cxy;
|
|
m_cxDragMin = m_rgHeaderItem[pHeaderNotify->iItem].cxItemMin;
|
|
m_cxDragMax = m_cxWnd;
|
|
m_xDragStart = 0;
|
|
for (i = 0; i < pHeaderNotify->iItem; i++)
|
|
{
|
|
x = m_rgHeaderItem[i].cxItemCurrent;
|
|
m_cxDragMax -= x;
|
|
m_xDragStart += x;
|
|
}
|
|
while (i < m_cHeaderItem)
|
|
m_cxDragMax -= m_rgHeaderItem[i++].cxItemMin;
|
|
Report(m_cxDragMax > 0);
|
|
Report(m_xDragStart <= m_cxWnd);
|
|
DrawListBoxLine();
|
|
Trace4(mskTraceLocalDebug, "\nHDN_BEGINTRACK [iItem=%d]: m_xDragStart=%d, m_cxDragMin=%d, m_cxDragMax=%d.",
|
|
pHeaderNotify->iItem, m_xDragStart, m_cxDragMin, m_cxDragMax);
|
|
break;
|
|
|
|
case HDN_TRACK:
|
|
Assert(pHeaderNotify->pitem != NULL);
|
|
Assert(pHeaderNotify->pitem->mask & HDI_WIDTH);
|
|
if (pHeaderNotify->iItem >= m_cHeaderItem - 1)
|
|
break;
|
|
if (pHeaderNotify->pitem->cxy < m_cxDragMin)
|
|
pHeaderNotify->pitem->cxy = m_cxDragMin;
|
|
if (pHeaderNotify->pitem->cxy > m_cxDragMax)
|
|
pHeaderNotify->pitem->cxy = m_cxDragMax;
|
|
if (m_cxDragCurrent == pHeaderNotify->pitem->cxy)
|
|
break;
|
|
DrawListBoxLine();
|
|
m_cxDragCurrent = pHeaderNotify->pitem->cxy;
|
|
DrawListBoxLine();
|
|
Trace1(mskTraceLocalDebug, "\nHDN_TRACK: %d.", pHeaderNotify->pitem->cxy);
|
|
break;
|
|
|
|
case HDN_ENDTRACK:
|
|
Assert(pHeaderNotify->pitem != NULL);
|
|
if (pHeaderNotify->iItem >= m_cHeaderItem - 1)
|
|
{
|
|
Trace0(mskTraceLocalDebug, "\nHDN_ENDTRACK: NoDrag");
|
|
break;
|
|
}
|
|
Assert(pHeaderNotify->iItem >= 0);
|
|
Assert(m_cxDragCurrent >= m_cxDragMin);
|
|
DrawListBoxLine();
|
|
m_rgHeaderItem[pHeaderNotify->iItem].cxItemCurrent = m_cxDragCurrent;
|
|
Trace0(mskTraceLocalDebug, "\nHDN_ENDTRACK: [");
|
|
x = 0;
|
|
for (i = 0; i < m_cHeaderItem - 1; i++)
|
|
{
|
|
x += m_rgHeaderItem[i].cxItemCurrent;
|
|
Trace1(mskTraceLocalDebug, " %d ", m_rgHeaderItem[i].cxItemCurrent);
|
|
}
|
|
hdi.cxy = m_cxWnd - x;
|
|
// Resize the last item
|
|
if (hdi.cxy > 0)
|
|
{
|
|
hdi.mask = HDI_WIDTH;
|
|
SideReport(Header_SetItem(m_hWnd, i, IN &hdi));
|
|
}
|
|
Trace1(mskTraceLocalDebug, "] %d.", hdi.cxy);
|
|
Assert(IsWindow(m_hwndListBox));
|
|
InvalidateRect(m_hwndListBox, NULL, FALSE);
|
|
break;
|
|
} // switch
|
|
|
|
return FALSE;
|
|
} // CWndHeader::OnNotify
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void SubclassListBoxEx(HWND hwndListBox)
|
|
{
|
|
AssertClassName(hwndListBox, szClassListBox);
|
|
Assert((WNDPROC)GetWindowLong(hwndListBox, GWL_WNDPROC) == lpfnListBoxOld);
|
|
SetWindowLong(hwndListBox, GWL_WNDPROC, (LONG)WndProcListBoxEx);
|
|
} // SubclassListBoxEx
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void LB_HandleMouseClick(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
MOUSECLICKINFO mci;
|
|
HWND hwndParent;
|
|
RECT rcListBox;
|
|
int cItems; // Number of items in listbox
|
|
int i;
|
|
|
|
mci.hwndFrom = hwnd;
|
|
mci.wId = GetDlgCtrlID(hwnd);
|
|
mci.uAction = uMsg;
|
|
mci.uMouseFlags = wParam;
|
|
mci.ptMouse.x = LOWORD(lParam);
|
|
mci.ptMouse.y = HIWORD(lParam);
|
|
mci.iItem = LB_ERR;
|
|
mci.lParam = NULL;
|
|
|
|
Assert(IsWindow(hwnd));
|
|
hwndParent = GetParent(hwnd);
|
|
Assert(IsWindow(hwndParent));
|
|
SideAssert(GetClientRect(hwnd, OUT &rcListBox));
|
|
Assert(lpfnListBoxOld != NULL);
|
|
// Get number of elements in listbox
|
|
cItems = CallWindowProc(lpfnListBoxOld, hwnd, LB_GETCOUNT, 0, 0);
|
|
Report(cItems >= 0);
|
|
// Get the top index
|
|
i = CallWindowProc(lpfnListBoxOld, hwnd, LB_GETTOPINDEX, 0, 0);
|
|
Report(i >= 0 && (i < cItems || cItems == 0));
|
|
// Do some primitive hit-testing
|
|
while (i < cItems)
|
|
{
|
|
RECT rcItem;
|
|
|
|
DebugCode( LRESULT lResult = ) CallWindowProc(lpfnListBoxOld, hwnd,
|
|
LB_GETITEMRECT, i, OUT (LPARAM)&rcItem);
|
|
Report(lResult != LB_ERR);
|
|
#ifdef DEBUG
|
|
int cyItem = CallWindowProc(lpfnListBoxOld, hwnd,
|
|
LB_GETITEMHEIGHT, i, 0);
|
|
Assert(cyItem == rcItem.bottom - rcItem.top);
|
|
#endif // DEBUG
|
|
if (rcItem.top > rcListBox.bottom)
|
|
break;
|
|
if (PtInRect(&rcItem, mci.ptMouse))
|
|
{
|
|
mci.iItem = i;
|
|
break;
|
|
}
|
|
i++;
|
|
} // while
|
|
(void)SendMessage(hwndParent, UN_MOUSECLICK, mci.wId, (LPARAM)&mci);
|
|
|
|
#ifdef UNUSED
|
|
// REVIEW: This code is not necessary
|
|
Trace0(mci.uAction != uMsg ? mskTraceLocalDebug : mskTraceNone, "\nUN_MOUSECLICK: uAction changed");
|
|
Trace0(mci.iItem != i && i < cItems ? mskTraceAlways : mskTraceNone, "\nUN_MOUSECLICK: iItem changed");
|
|
if (mci.uAction == WM_LBUTTONDOWN && mci.iItem >= 0)
|
|
{
|
|
DebugCode( LRESULT lResult = ) CallWindowProc(lpfnListBoxOld,
|
|
hwnd, LB_SETCURSEL, mci.iItem, 0);
|
|
Report(lResult != LB_ERR);
|
|
Report(mci.iItem == CallWindowProc(lpfnListBoxOld, hwnd, LB_GETCURSEL, 0, 0));
|
|
// Notify the parent that the selection changed
|
|
SendMessage(hwndParent, WM_COMMAND,
|
|
MAKEWPARAM(mci.wId, LBN_SELCHANGE), (LPARAM)hwnd);
|
|
} // if
|
|
#endif // UNUSED
|
|
|
|
} // LB_HandleMouseClick
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
LRESULT CALLBACK WndProcListBoxEx(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_KEYDOWN:
|
|
if (0 != LSendMessage(GetParent(hwnd), UN_KEYDOWN, wParam, (LPARAM)hwnd))
|
|
return 0;
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
LB_HandleMouseClick(hwnd, uMsg, wParam, lParam);
|
|
return 0;
|
|
} // switch
|
|
|
|
Assert(lpfnListBoxOld != NULL);
|
|
return CallWindowProc(lpfnListBoxOld, hwnd, uMsg, wParam, lParam);
|
|
} // WndProcListBoxEx
|
|
|
|
|