HEADING.C

/************************************************************************* 
**
** OLE 2 Sample Code
**
** heading.c
**
** This file contains functions and support for OutlineDoc's row and
** column headings.
**
** (c) Copyright Microsoft Corp. 1992 - 1996 All Rights Reserved
**
*************************************************************************/

#include "outline.h"

extern LPOUTLINEAPP g_lpApp;


BOOL Heading_Create(LPHEADING lphead, HWND hWndParent, HINSTANCE hInst)
{
HDC hDC;
TEXTMETRIC tm;

if (!lphead || !hWndParent || !hInst)
return FALSE;

hDC = GetDC(hWndParent);
if (!hDC)
return FALSE;

if (!GetTextMetrics(hDC, (TEXTMETRIC FAR*)&tm))
return FALSE;
lphead->m_colhead.m_uHeight = tm.tmHeight;
lphead->m_rowhead.m_uWidth = 4 * tm.tmAveCharWidth;
lphead->m_fShow = TRUE;

ReleaseDC(hWndParent, hDC);

lphead->m_hfont = CreateFont(
tm.tmHeight,
0,0,0,0,0,0,0,0,
OUT_TT_PRECIS, // use TrueType
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
HEADING_FONT
);

if (!lphead->m_hfont)
return FALSE;

lphead->m_colhead.m_hWnd = CreateWindow(
"listbox",
"Column Heading",
WS_VISIBLE | WS_CHILD | WS_DISABLED | LBS_OWNERDRAWVARIABLE |
LBS_NOINTEGRALHEIGHT,
0,0,0,0, // any values
hWndParent,
(HMENU)IDC_COLHEADING,
hInst,
NULL);

if (!lphead->m_colhead.m_hWnd)
return FALSE;

// add a dummy line to get WM_DRAWITEM message
SendMessage(lphead->m_colhead.m_hWnd, LB_ADDSTRING, 0,
MAKELPARAM(lphead->m_colhead.m_uHeight,0));

lphead->m_rowhead.m_hWnd = CreateWindow(
"listbox",
"Row Heading",
WS_VISIBLE | WS_CHILD | WS_DISABLED | LBS_OWNERDRAWVARIABLE,
0,0,0,0, // any values
hWndParent,
(HMENU)IDC_ROWHEADING,
hInst,
NULL);

if (!lphead->m_rowhead.m_hWnd)
return FALSE;

SendMessage(lphead->m_rowhead.m_hWnd, LB_ADDSTRING, 0,
MAKELPARAM(lphead->m_colhead.m_uHeight,0));

lphead->m_rowhead.m_WndProc =
(FARPROC) GetWindowLong(lphead->m_rowhead.m_hWnd, GWL_WNDPROC );
SetWindowLong(lphead->m_rowhead.m_hWnd, GWL_WNDPROC,
(LONG) RowHeadWndProc);

lphead->m_hwndButton = CreateWindow(
"button",
NULL,
WS_VISIBLE | WS_CHILD,
0,0,0,0, // any values
hWndParent,
(HMENU)IDC_BUTTON,
hInst,
NULL);

if (!lphead->m_hwndButton)
return FALSE;

return TRUE;
}


void Heading_Destroy(LPHEADING lphead)
{
if (!lphead)
return;

if (IsWindow(lphead->m_colhead.m_hWnd)) {
DestroyWindow(lphead->m_colhead.m_hWnd);
lphead->m_colhead.m_hWnd = NULL;
}
if (IsWindow(lphead->m_rowhead.m_hWnd)) {
DestroyWindow(lphead->m_rowhead.m_hWnd);
lphead->m_rowhead.m_hWnd = NULL;
}
if (IsWindow(lphead->m_hwndButton)) {
DestroyWindow(lphead->m_hwndButton);
lphead->m_hwndButton = NULL;
}
#ifdef WIN32
if (GetObjectType(lphead->m_hfont)) {
#else
if (IsGDIObject(lphead->m_hfont)) {
#endif
DeleteObject(lphead->m_hfont);
lphead->m_hfont = NULL;
}

}


void Heading_Move(LPHEADING lphead, HWND hwndDoc, LPSCALEFACTOR lpscale)
{
int nOffsetX;
int nOffsetY;
RECT rcDoc;

if (!lphead || !hwndDoc || !lpscale)
return;

if (!lphead->m_fShow)
return;

nOffsetX = (int) Heading_RH_GetWidth(lphead, lpscale);
nOffsetY = (int) Heading_CH_GetHeight(lphead, lpscale);
GetClientRect(hwndDoc, (LPRECT)&rcDoc);

MoveWindow(lphead->m_hwndButton, 0, 0, nOffsetX, nOffsetY, TRUE);

MoveWindow(
lphead->m_colhead.m_hWnd,
nOffsetX, 0,
rcDoc.right-rcDoc.left-nOffsetX, nOffsetY,
TRUE
);

MoveWindow(lphead->m_rowhead.m_hWnd, 0, nOffsetY, nOffsetX,
rcDoc.bottom-rcDoc.top-nOffsetY, TRUE);
}


void Heading_Show(LPHEADING lphead, BOOL fShow)
{
int nCmdShow;

if (!lphead)
return;

lphead->m_fShow = fShow;
nCmdShow = fShow ? SW_SHOW : SW_HIDE;

ShowWindow(lphead->m_hwndButton, nCmdShow);
ShowWindow(lphead->m_colhead.m_hWnd, nCmdShow);
ShowWindow(lphead->m_rowhead.m_hWnd, nCmdShow);
}


void Heading_ReScale(LPHEADING lphead, LPSCALEFACTOR lpscale)
{
UINT uHeight;

if (!lphead || !lpscale)
return;

// Row heading is scaled with the LineList_Rescale. So, only
// Column heading needed to be scaled here.
uHeight = (UINT)(lphead->m_colhead.m_uHeight * lpscale->dwSyN /
lpscale->dwSyD);
SendMessage(lphead->m_colhead.m_hWnd, LB_SETITEMHEIGHT, 0,
MAKELPARAM(uHeight, 0));
}


void Heading_CH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis, LPRECT lprcScreen, LPRECT lprcObject)
{
HPEN hpenOld;
HPEN hpen;
HBRUSH hbr;
HFONT hfOld;
int nTabInPix;
char letter;
int i;
int nOldMapMode;
RECT rcWindowOld;
RECT rcViewportOld;
POINT point;

if (!lpdis || !lphead)
return;

hbr = GetStockObject(LTGRAY_BRUSH);
FillRect(lpdis->hDC, (LPRECT)&lpdis->rcItem, hbr);

nOldMapMode = SetDCToAnisotropic(lpdis->hDC, lprcScreen, lprcObject,
(LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);

hfOld = SelectObject(lpdis->hDC, lphead->m_hfont);
hpen = GetStockObject(BLACK_PEN);
hpenOld = SelectObject(lpdis->hDC, hpen);

nTabInPix = XformWidthInHimetricToPixels(lpdis->hDC, TABWIDTH);
SetBkMode(lpdis->hDC, TRANSPARENT);

letter = COLUMN_LETTER;
MoveToEx(lpdis->hDC, lprcObject->left, lprcObject->bottom,&point);
LineTo(lpdis->hDC, lprcObject->left, lprcObject->top);

for (i = 0; i < COLUMN; i++) {
lprcObject->right = lprcObject->left + nTabInPix;
DrawText(lpdis->hDC, (LPCSTR)&letter, 1, lprcObject,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
MoveToEx(lpdis->hDC, lprcObject->right, lprcObject->bottom, &point);
LineTo(lpdis->hDC, lprcObject->right, lprcObject->top);

letter++;
lprcObject->left += nTabInPix;
}

SelectObject(lpdis->hDC, hpenOld);
SelectObject(lpdis->hDC, hfOld);

ResetOrigDC(lpdis->hDC, nOldMapMode, (LPRECT)&rcWindowOld,
(LPRECT)&rcViewportOld);
}


void Heading_CH_SetHorizontalExtent(LPHEADING lphead, HWND hwndListBox)
{
RECT rcLL;
RECT rcCH;
int nLLWidth;
int nCHWidth;
int nHorizExtent;

if (!lphead || !hwndListBox)
return;

nHorizExtent=(int)SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0L);
GetClientRect(hwndListBox, (LPRECT)&rcLL);
GetClientRect(lphead->m_colhead.m_hWnd, (LPRECT)&rcCH);

nLLWidth = rcLL.right - rcLL.left;
nCHWidth = rcCH.right - rcCH.left;
nHorizExtent += nCHWidth - nLLWidth;

SendMessage(lphead->m_colhead.m_hWnd, LB_SETHORIZONTALEXTENT,
nHorizExtent, 0L);
}


UINT Heading_CH_GetHeight(LPHEADING lphead, LPSCALEFACTOR lpscale)
{
if (!lphead || !lpscale)
return 0;

if (lphead->m_fShow)
return (UINT)(lphead->m_colhead.m_uHeight * lpscale->dwSyN /
lpscale->dwSyD);
else
return 0;
}


LRESULT Heading_CH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (!lphead)
return 0;

if (lphead->m_colhead.m_hWnd)
return SendMessage(lphead->m_colhead.m_hWnd, msg, wParam, lParam);
}


void Heading_CH_ForceRedraw(LPHEADING lphead, BOOL fErase)
{
if (!lphead)
return;

InvalidateRect(lphead->m_colhead.m_hWnd, NULL, fErase);
}

void Heading_RH_ForceRedraw(LPHEADING lphead, BOOL fErase)
{
if (!lphead)
return;

InvalidateRect(lphead->m_rowhead.m_hWnd, NULL, fErase);
}

void Heading_RH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis)
{
char cBuf[5];
HPEN hpenOld;
HPEN hpen;
HBRUSH hbrOld;
HBRUSH hbr;
HFONT hfOld;
RECT rc;
RECT rcWindowOld;
RECT rcViewportOld;
int nMapModeOld;

if (!lpdis || !lphead)
return;

lpdis->rcItem;

rc.left = 0;
rc.bottom = 0;
rc.top = (int)lpdis->itemData;
rc.right = lphead->m_rowhead.m_uWidth;

nMapModeOld = SetDCToAnisotropic(lpdis->hDC, &lpdis->rcItem, &rc,
(LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);

hpen = GetStockObject(BLACK_PEN);
hpenOld = SelectObject(lpdis->hDC, hpen);
hbr = GetStockObject(LTGRAY_BRUSH);
hbrOld = SelectObject(lpdis->hDC, hbr);

Rectangle(lpdis->hDC, rc.left, rc.top, rc.right,
rc.bottom);

hfOld = SelectObject(lpdis->hDC, lphead->m_hfont);

SetBkMode(lpdis->hDC, TRANSPARENT);

wsprintf(cBuf, "%d", lpdis->itemID + 1);

DrawText(lpdis->hDC, (LPSTR)cBuf, lstrlen(cBuf), (LPRECT)&rc,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);

SelectObject(lpdis->hDC, hfOld);

SelectObject(lpdis->hDC, hpenOld);
SelectObject(lpdis->hDC, hbrOld);

ResetOrigDC(lpdis->hDC, nMapModeOld, (LPRECT)&rcWindowOld,
(LPRECT)&rcViewportOld);
}

LRESULT Heading_RH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (!lphead)
return 0;

if (lphead->m_rowhead.m_hWnd)
return SendMessage(lphead->m_rowhead.m_hWnd, msg, wParam, lParam);
}


UINT Heading_RH_GetWidth(LPHEADING lphead, LPSCALEFACTOR lpscale)
{
if (!lphead || !lpscale)
return 0;

if (lphead->m_fShow)
return (UINT)(lphead->m_rowhead.m_uWidth * lpscale->dwSxN /
lpscale->dwSxD);
else
return 0;
}


void Heading_RH_Scroll(LPHEADING lphead, HWND hwndListBox)
{
int nTopLL;
int nTopRH;

if (!lphead || !hwndListBox)
return;

nTopLL = (int)SendMessage(hwndListBox, LB_GETTOPINDEX, 0, 0L);
nTopRH = (int)SendMessage(
lphead->m_rowhead.m_hWnd, LB_GETTOPINDEX, 0, 0L);

if (nTopLL != nTopRH)
SendMessage(
lphead->m_rowhead.m_hWnd,LB_SETTOPINDEX,(WPARAM)nTopLL,0L);
}


LRESULT FAR PASCAL RowHeadWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
HWND hwndParent = GetParent (hWnd);
LPOUTLINEDOC lpDoc = (LPOUTLINEDOC)GetWindowLong(hwndParent, 0);
LPHEADING lphead = OutlineDoc_GetHeading(lpDoc);

switch (Message) {
case WM_PAINT:
{
LPLINELIST lpLL = OutlineDoc_GetLineList(lpDoc);
PAINTSTRUCT ps;

// If there is no line in listbox, trap the message and draw the
// background gray. Without this, the background will be painted
// as default color.
if (!LineList_GetCount(lpLL)) {
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
}

break;
}

case WM_ERASEBKGND:
{
HDC hDC = (HDC)wParam;
RECT rc;

GetClientRect(hWnd, (LPRECT)&rc);
FillRect(hDC, (LPRECT)&rc, GetStockObject(GRAY_BRUSH));

return 1;
}
}

return CallWindowProc(
(WNDPROC)lphead->m_rowhead.m_WndProc,
hWnd,
Message,
wParam,
lParam
);
}