|
|
//---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation 1993-1994
//
// File: recact.c
//
// This file contains the reconciliation-action control class code
//
//
// History:
// 08-12-93 ScottH Created.
//
//---------------------------------------------------------------------------
///////////////////////////////////////////////////// INCLUDES
#include "pch.h"
#include "reintinc.h"
#include "extra.h"
#include "resource.h"
#include "recact.h"
#include "dobj.h"
///////////////////////////////////////////////////// Globals
int g_cxIconSpacing = 0; int g_cyIconSpacing = 0; int g_cxBorder = 0; int g_cyBorder = 0;
int g_cxMargin = 0; int g_cxIcon = 0; int g_cyIcon = 0; int g_cxIconMargin = 0; int g_cyIconMargin = 0;
int g_cxLabelMargin = 0; int g_cyLabelSpace = 0;
//char const FAR c_szWinHelpFile[] = "windows.hlp";
///////////////////////////////////////////////////// CONTROLLING DEFINES
///////////////////////////////////////////////////// DEFINES
// Manifest constants
#define SIDE_INSIDE 0
#define SIDE_OUTSIDE 1
// These should be changed if the bitmap sizes change!!
#define CX_ACTIONBMP 26
#define CY_ACTIONBMP 26
#define RECOMPUTE (-1)
#define X_INCOLUMN (g_cxIcon*2)
// Image indexes
#define II_RIGHT 0
#define II_LEFT 1
#define II_CONFLICT 2
#define II_SKIP 3
#define II_MERGE 4
#define II_SOMETHING 5
#define II_UPTODATE 6
// Menu items
//
#define IDM_ACTIONFIRST 100
#define IDM_TOOUT 100
#define IDM_TOIN 101
#define IDM_SKIP 102
#define IDM_MERGE 103
#define IDM_ACTIONLAST 103
#define IDM_WHATSTHIS 104
///////////////////////////////////////////////////// TYPEDEFS
typedef struct tagRECACT { HWND hwnd; HWND hwndLB; HDC hdcOwn; // Own DC
HMENU hmenu; // Action and help context menu
HFONT hfont; WNDPROC lpfnLBProc; // Default LB proc
HIMAGELIST himlAction; // imagelist for actions
HIMAGELIST himlCache; // control imagelist cache
HBITMAP hbmpBullet;
HBRUSH hbrBkgnd; COLORREF clrBkgnd;
LONG lStyle; // Window style flags
// Metrics
int xAction; int cxAction; int cxItem; // Generic width of an item
int cxMenuCheck; int cyMenuCheck; int cyText; int cxSideItem; int cxEllipses;
} RECACT, FAR * LPRECACT;
#define RecAct_IsNoIcon(this) IsFlagSet((this)->lStyle, RAS_SINGLEITEM)
// Internal item data struct
//
typedef struct tagRA_PRIV { UINT uStyle; // One of RAIS_
UINT uAction; // One of RAIA_
FileInfo * pfi;
SIDEITEM siInside; SIDEITEM siOutside;
LPARAM lParam;
DOBJ rgdobj[4]; // Array of Draw object info
int cx; // Bounding width and height
int cy;
} RA_PRIV, FAR * LPRA_PRIV;
#define IDOBJ_ACTION 3
// RecAction menu item definition structure. Used to define the
// context menu brought up in this control.
//
typedef struct tagRAMID { UINT idm; // Menu ID (for MENUITEMINFO struct)
UINT uAction; // One of RAIA_* flags
UINT ids; // Resource string ID
int iImage; // Index into himlAction
RECT rcExtent; // Extent rect of string
} RAMID, FAR * LPRAMID; // RecAction Menu Item Definition
// Help menu item definition structure. Used to define the help
// items in the context menu.
//
typedef struct tagHMID { UINT idm; UINT ids; } HMID;
///////////////////////////////////////////////////// MACROS
#define RecAct_DefProc DefWindowProc
#define RecActLB_DefProc CallWindowProc
// Instance data pointer macros
//
#define RecAct_GetPtr(hwnd) (LPRECACT)GetWindowLong(hwnd, 0)
#define RecAct_SetPtr(hwnd, lp) (LPRECACT)SetWindowLong(hwnd, 0, (LONG)(lp))
#define RecAct_GetCount(this) ListBox_GetCount((this)->hwndLB)
///////////////////////////////////////////////////// MODULE DATA
static char const c_szEllipses[] = "..."; static char const c_szDateDummy[] = "99/99/99 99:99PM";
// Map RAIA_* values to image indexes
//
static UINT const c_mpraiaiImage[] = { II_RIGHT, II_LEFT, II_SKIP, II_CONFLICT, II_MERGE, II_SOMETHING, II_UPTODATE };
// Map RAIA_* values to menu command positions
//
static UINT const c_mpraiaidmMenu[] = {IDM_TOOUT, IDM_TOIN, IDM_SKIP, IDM_SKIP, IDM_MERGE, 0, 0 };
// Define the context menu layout
//
static RAMID const c_rgramid[] = { { IDM_TOOUT, RAIA_TOOUT, IDS_MENU_REPLACE, II_RIGHT, 0 }, { IDM_TOIN, RAIA_TOIN, IDS_MENU_REPLACE, II_LEFT, 0 }, { IDM_SKIP, RAIA_SKIP, IDS_MENU_SKIP, II_SKIP, 0 }, // Merge must be the last item!
{ IDM_MERGE, RAIA_MERGE, IDS_MENU_MERGE, II_MERGE, 0 }, };
static RAMID const c_rgramidCreates[] = { { IDM_TOOUT, RAIA_TOOUT, IDS_MENU_CREATE, II_RIGHT, 0 }, { IDM_TOIN, RAIA_TOIN, IDS_MENU_CREATE, II_LEFT, 0 }, };
// Indexes into c_rgramidCreates
//
#define IRAMID_CREATEOUT 0
#define IRAMID_CREATEIN 1
static HMID const c_rghmid[] = { { IDM_WHATSTHIS, IDS_MENU_WHATSTHIS }, };
///////////////////////////////////////////////////// LOCAL PROCEDURES
LRESULT _export CALLBACK RecActLB_LBProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
///////////////////////////////////////////////////// PRIVATE FUNCTIONS
#ifdef DEBUG
LPCSTR PRIVATE DumpRecAction( UINT uAction) // RAIA_
{ switch (uAction) { DEBUG_CASE_STRING( RAIA_TOOUT ); DEBUG_CASE_STRING( RAIA_TOIN ); DEBUG_CASE_STRING( RAIA_SKIP ); DEBUG_CASE_STRING( RAIA_CONFLICT ); DEBUG_CASE_STRING( RAIA_MERGE ); DEBUG_CASE_STRING( RAIA_SOMETHING ); DEBUG_CASE_STRING( RAIA_NOTHING ); DEBUG_CASE_STRING( RAIA_ORPHAN );
default: return "Unknown"; } }
LPCSTR PRIVATE DumpSideItemState( UINT uState) // SI_
{ switch (uState) { DEBUG_CASE_STRING( SI_UNCHANGED ); DEBUG_CASE_STRING( SI_CHANGED ); DEBUG_CASE_STRING( SI_NEW ); DEBUG_CASE_STRING( SI_NOEXIST ); DEBUG_CASE_STRING( SI_UNAVAILABLE ); DEBUG_CASE_STRING( SI_DELETED );
default: return "Unknown"; } }
/*----------------------------------------------------------
Purpose: Returns: Cond: -- */ void PUBLIC DumpTwinPair( LPRA_ITEM pitem) { if (pitem) { char szBuf[MAXMSGLEN];
#define szDump "Dump TWINPAIR: "
#define szBlank " "
if (IsFlagClear(g_uDumpFlags, DF_TWINPAIR)) { return; }
wsprintf(szBuf, "%s.pszName = %s\r\n", (LPSTR)szDump, Dbg_SafeStr(pitem->pszName)); OutputDebugString(szBuf); wsprintf(szBuf, "%s.uStyle = %lx\r\n", (LPSTR)szBlank, pitem->uStyle); OutputDebugString(szBuf); wsprintf(szBuf, "%s.uAction = %s\r\n", (LPSTR)szBlank, DumpRecAction(pitem->uAction)); OutputDebugString(szBuf);
#undef szDump
#define szDump " Inside: "
wsprintf(szBuf, "%s.pszDir = %s\r\n", (LPSTR)szDump, Dbg_SafeStr(pitem->siInside.pszDir)); OutputDebugString(szBuf); wsprintf(szBuf, "%s.uState = %s\r\n", (LPSTR)szBlank, DumpSideItemState(pitem->siInside.uState)); OutputDebugString(szBuf);
#undef szDump
#define szDump " Outside: "
wsprintf(szBuf, "%s.pszDir = %s\r\n", (LPSTR)szDump, Dbg_SafeStr(pitem->siOutside.pszDir)); OutputDebugString(szBuf); wsprintf(szBuf, "%s.uState = %s\r\n", (LPSTR)szBlank, DumpSideItemState(pitem->siOutside.uState)); OutputDebugString(szBuf);
#undef szDump
#undef szBlank
} }
#endif
/*----------------------------------------------------------
Purpose: Create a monochrome bitmap of the bullet, so we can play with the colors later. Returns: handle to bitmap Cond: Caller must delete bitmap */ HBITMAP PRIVATE CreateBulletBitmap( LPSIZE psize) { HDC hdcMem; HBITMAP hbmp = NULL;
hdcMem = CreateCompatibleDC(NULL); if (hdcMem) { hbmp = CreateCompatibleBitmap(hdcMem, psize->cx, psize->cy); if (hbmp) { HBITMAP hbmpOld; RECT rc;
// hbmp is monochrome
hbmpOld = SelectBitmap(hdcMem, hbmp); rc.left = 0; rc.top = 0; rc.right = psize->cx; rc.bottom = psize->cy; DrawFrameControl(hdcMem, &rc, DFC_MENU, DFCS_MENUBULLET);
SelectBitmap(hdcMem, hbmpOld); } DeleteDC(hdcMem); } return hbmp; }
/*----------------------------------------------------------
Purpose: Returns the resource ID string given the action flag. Returns: IDS_ value Cond: -- */ UINT PRIVATE GetActionText( LPRA_PRIV ppriv) { UINT ids;
ASSERT(ppriv);
switch (ppriv->uAction) { case RAIA_TOOUT: if (SI_NEW == ppriv->siInside.uState) { ids = IDS_STATE_Creates; } else { ids = IDS_STATE_Replaces; } break;
case RAIA_TOIN: if (SI_NEW == ppriv->siOutside.uState) { ids = IDS_STATE_Creates; } else { ids = IDS_STATE_Replaces; } break;
case RAIA_SKIP: // Can occur if the user explicitly wants to skip, or if
// one side is unavailable.
ids = IDS_STATE_Skip; break;
case RAIA_CONFLICT: ids = IDS_STATE_Conflict; break; case RAIA_MERGE: ids = IDS_STATE_Merge; break; case RAIA_NOTHING: ids = IDS_STATE_Uptodate; break; case RAIA_SOMETHING: ids = IDS_STATE_NeedToUpdate; break; default: ids = 0; break; }
return ids; }
/*----------------------------------------------------------
Purpose: Repaint an item in the listbox Returns: -- Cond: -- */ void PRIVATE ListBox_RepaintItemNow( HWND hwnd, int iItem, LPRECT prc, // Relative to individual entry rect. May be NULL
BOOL bEraseBk) { RECT rc; RECT rcItem;
ListBox_GetItemRect(hwnd, iItem, &rcItem); if (prc) { OffsetRect(prc, rcItem.left, rcItem.top); IntersectRect(&rc, &rcItem, prc); } else rc = rcItem;
InvalidateRect(hwnd, &rc, bEraseBk); UpdateWindow(hwnd); }
/*----------------------------------------------------------
Purpose: Send selection change notification Returns: Cond: -- */ BOOL PRIVATE RecAct_SendSelChange( LPRECACT this, int isel) { NM_RECACT nm; nm.iItem = isel; nm.mask = 0; if (isel != -1) { LPRA_ITEM pitem; ListBox_GetText(this->hwndLB, isel, &pitem); if (!pitem) return FALSE; nm.lParam = pitem->lParam; nm.mask |= RAIF_LPARAM; } return !(BOOL)SendNotify(GetParent(this->hwnd), this->hwnd, RN_SELCHANGED, &nm.hdr); }
/*----------------------------------------------------------
Purpose: Send an action change notification Returns: Cond: -- */ BOOL PRIVATE RecAct_SendItemChange( LPRECACT this, int iEntry, UINT uActionOld) { NM_RECACT nm; nm.iItem = iEntry; nm.mask = 0; if (iEntry != -1) { LPRA_PRIV ppriv; ListBox_GetText(this->hwndLB, iEntry, &ppriv); if (!ppriv) return FALSE; nm.mask |= RAIF_LPARAM | RAIF_ACTION; nm.lParam = ppriv->lParam; nm.uAction = ppriv->uAction; nm.uActionOld = uActionOld; } return !(BOOL)SendNotify(GetParent(this->hwnd), this->hwnd, RN_ITEMCHANGED, &nm.hdr); }
/*----------------------------------------------------------
Purpose: Calculate the important coordinates that we want to save. Returns: -- Cond: -- */ void PRIVATE RecAct_CalcCoords( LPRECACT this) { int xOutColumn; ASSERT(this->cxSideItem != 0); xOutColumn = this->cxItem - this->cxSideItem - g_cxMargin;
this->xAction = (RecAct_IsNoIcon(this) ? 0 : X_INCOLUMN) + this->cxSideItem; this->cxAction = xOutColumn - this->xAction; }
/*----------------------------------------------------------
Purpose: Create the action context menu Returns: TRUE on success Cond: -- */ BOOL PRIVATE RecAct_CreateMenu( LPRECACT this) { HMENU hmenu;
hmenu = CreatePopupMenu(); if (hmenu) { char sz[MAXSHORTLEN]; MENUITEMINFO mii; int i;
// Add the help menu items now, since these will be standard
//
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID; mii.fType = MFT_STRING; mii.fState = MFS_ENABLED;
for (i = 0; i < ARRAYSIZE(c_rghmid); i++) { mii.wID = c_rghmid[i].idm; mii.dwTypeData = SzFromIDS(c_rghmid[i].ids, sz, sizeof(sz)); InsertMenuItem(hmenu, i, TRUE, &mii); }
this->hmenu = hmenu; }
return hmenu != NULL; }
/*----------------------------------------------------------
Purpose: Add the action menu items to the context menu Returns: -- Cond: -- */ void PRIVATE AddActionsToContextMenu( HMENU hmenu, UINT idmCheck, // menu item to checkmark
LPRA_PRIV ppriv) { MENUITEMINFO mii; int i; int cItems = ARRAYSIZE(c_rgramid);
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA; mii.fType = MFT_OWNERDRAW; mii.fState = MFS_ENABLED;
// Is merge supported?
if (IsFlagClear(ppriv->uStyle, RAIS_CANMERGE)) { // No
--cItems; }
for (i = 0; i < cItems; i++) { mii.wID = c_rgramid[i].idm; mii.dwItemData = (DWORD)&c_rgramid[i];
InsertMenuItem(hmenu, i, TRUE, &mii); }
// Add the separator
mii.fMask = MIIM_TYPE; mii.fType = MFT_SEPARATOR; InsertMenuItem(hmenu, i, TRUE, &mii);
// Set the initial checkmark.
CheckMenuRadioItem(hmenu, IDM_ACTIONFIRST, IDM_ACTIONLAST, idmCheck, MF_BYCOMMAND | MF_CHECKED);
#if 0
// Is merge supported?
if (IsFlagClear(ppriv->uStyle, RAIS_CANMERGE)) { // No
mii.fMask = MIIM_STATE; mii.fState = MFS_GRAYED | MFS_DISABLED; SetMenuItemInfo(hmenu, IDM_MERGE, FALSE, &mii); } #endif
//tHACK
mii.fMask = MIIM_STATE; mii.fState = MFS_GRAYED | MFS_DISABLED; SetMenuItemInfo(hmenu, IDM_SKIP, FALSE, &mii);
// Is the file or its sync copy unavailable?
if (SI_UNAVAILABLE == ppriv->siInside.uState || SI_UNAVAILABLE == ppriv->siOutside.uState) { // Yes
mii.fMask = MIIM_STATE; mii.fState = MFS_GRAYED | MFS_DISABLED; SetMenuItemInfo(hmenu, IDM_TOIN, FALSE, &mii); SetMenuItemInfo(hmenu, IDM_TOOUT, FALSE, &mii); SetMenuItemInfo(hmenu, IDM_MERGE, FALSE, &mii); }
// Is the file being created?
else if (ppriv->siInside.uState == SI_NEW || ppriv->siOutside.uState == SI_NEW) { // Yes; disable the replace-in-opposite direction
UINT idmDisable; UINT idmChangeVerb;
if (ppriv->siInside.uState == SI_NEW) { idmDisable = IDM_TOIN; idmChangeVerb = IDM_TOOUT; i = IRAMID_CREATEOUT; } else { idmDisable = IDM_TOOUT; idmChangeVerb = IDM_TOIN; i = IRAMID_CREATEIN; } // Disable one of the directions
mii.fMask = MIIM_STATE; mii.fState = MFS_GRAYED | MFS_DISABLED; SetMenuItemInfo(hmenu, idmDisable, FALSE, &mii);
// Change the verb of the other direction
mii.fMask = MIIM_DATA; mii.dwItemData = (DWORD)&c_rgramidCreates[i];
SetMenuItemInfo(hmenu, idmChangeVerb, FALSE, &mii); } }
/*----------------------------------------------------------
Purpose: Clear out the context menu Returns: -- Cond: -- */ void PRIVATE ResetContextMenu( HMENU hmenu) { int cnt;
// If there is more than just the help items, remove them
// (but leave the help items)
//
cnt = GetMenuItemCount(hmenu); if (cnt > ARRAYSIZE(c_rghmid)) { int i;
cnt -= ARRAYSIZE(c_rghmid); for (i = 0; i < cnt; i++) { DeleteMenu(hmenu, 0, MF_BYPOSITION); } } }
/*----------------------------------------------------------
Purpose: Do the context menu Returns: -- Cond: -- */ void PRIVATE RecAct_DoContextMenu( LPRECACT this, int x, // in screen coords
int y, int iEntry, BOOL bHelpOnly) // TRUE: only show the help items
{ UINT idCmd;
if (this->hmenu) { LPRA_PRIV ppriv; RECT rc; int idmCheck; UINT uActionOld;
// Only show help-portion of context menu?
if (bHelpOnly) { // Yes
ppriv = NULL; } else { // No
ListBox_GetText(this->hwndLB, iEntry, &ppriv);
// Determine if this is a help-context menu only.
// It is if this is a folder-item or if there is no action
// to take.
//
ASSERT(ppriv->uAction < ARRAYSIZE(c_mpraiaidmMenu)); idmCheck = c_mpraiaidmMenu[ppriv->uAction];
// Build the context menu
//
if (IsFlagClear(ppriv->uStyle, RAIS_FOLDER) && idmCheck != 0) { AddActionsToContextMenu(this->hmenu, idmCheck, ppriv); } }
// Show context menu
//
idCmd = TrackPopupMenu(this->hmenu, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTALIGN, x, y, 0, this->hwnd, NULL);
// Clear menu
//
ResetContextMenu(this->hmenu);
if (ppriv) { // Save the old action
uActionOld = ppriv->uAction; }
// Act on whatever the user chose
switch (idCmd) { case IDM_TOOUT: ppriv->uAction = RAIA_TOOUT; break;
case IDM_TOIN: ppriv->uAction = RAIA_TOIN; break;
case IDM_SKIP: ppriv->uAction = RAIA_SKIP; break;
case IDM_MERGE: ppriv->uAction = RAIA_MERGE; break;
// tHACK case IDM_WHATSTHIS:
// WinHelp(this->hwnd, c_szWinHelpFile, HELP_CONTEXTPOPUP, IDH_BFC_UPDATE_SCREEN);
// return; // Return now
default: return; // Return now
}
// Repaint action portion of entry
ppriv->cx = RECOMPUTE; rc = ppriv->rgdobj[IDOBJ_ACTION].rcBounding; ListBox_RepaintItemNow(this->hwndLB, iEntry, &rc, TRUE);
// Send a notify message
ASSERT(NULL != ppriv); // uActionOld should be valid
RecAct_SendItemChange(this, iEntry, uActionOld); } }
/*----------------------------------------------------------
Purpose: Create the windows for this control Returns: TRUE on success Cond: -- */ BOOL PRIVATE RecAct_CreateWindows( LPRECACT this, CREATESTRUCT FAR * lpcs) { HWND hwnd = this->hwnd; HWND hwndLB = NULL; RECT rc; int cxEdge = GetSystemMetrics(SM_CXEDGE); int cyEdge = GetSystemMetrics(SM_CYEDGE);
// Create listbox
hwndLB = CreateWindowEx( 0, "listbox", "", WS_CHILD | WS_CLIPSIBLINGS | LBS_SORT | LBS_OWNERDRAWVARIABLE | WS_VSCROLL | WS_TABSTOP | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY, 0, 0, lpcs->cx, lpcs->cy, hwnd, NULL, lpcs->hInstance, 0L); if (!hwndLB) return FALSE;
SetWindowFont(hwndLB, this->hfont, FALSE);
this->hwndLB = hwndLB;
// Determine layout of window
GetClientRect(hwnd, &rc); InflateRect(&rc, -cxEdge, -cyEdge); SetWindowPos(hwndLB, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOZORDER);
GetClientRect(hwndLB, &rc); this->cxItem = rc.right - rc.left;
return TRUE; }
/*----------------------------------------------------------
Purpose: Set the colors of the control Returns: -- Cond: -- */ void PRIVATE RecAct_SetColors( LPRECACT this) { int cr;
if (IsFlagClear(this->lStyle, RAS_SINGLEITEM)) { cr = COLOR_WINDOW; } else { cr = COLOR_3DFACE; }
this->clrBkgnd = GetSysColor(cr);
if (this->hbrBkgnd) DeleteBrush(this->hbrBkgnd);
this->hbrBkgnd = CreateSolidBrush(this->clrBkgnd); }
/*----------------------------------------------------------
Purpose: Creates an imagelist of the action images
Returns: TRUE on success
Cond: -- */ BOOL PRIVATE CreateImageList( HIMAGELIST * phiml, HDC hdc, UINT idb, int cxBmp, int cyBmp, int cImage) { BOOL bRet; HIMAGELIST himl;
himl = ImageList_Create(cxBmp, cyBmp, TRUE, cImage, 1);
if (himl) { COLORREF clrMask; HBITMAP hbm;
hbm = LoadBitmap(vhinstCur, MAKEINTRESOURCE(idb)); ASSERT(hbm);
if (hbm) { HDC hdcMem = CreateCompatibleDC(hdc); if (hdcMem) { HBITMAP hbmSav = SelectBitmap(hdcMem, hbm);
clrMask = GetPixel(hdcMem, 0, 0); SelectBitmap(hdcMem, hbmSav);
bRet = (0 == ImageList_AddMasked(himl, hbm, clrMask));
DeleteDC(hdcMem); } else bRet = FALSE;
DeleteBitmap(hbm); } else bRet = FALSE; } else bRet = FALSE;
*phiml = himl; return bRet; }
/*----------------------------------------------------------
Purpose: WM_CREATE handler Returns: TRUE on success Cond: -- */ BOOL PRIVATE RecAct_OnCreate( LPRECACT this, CREATESTRUCT FAR * lpcs) { BOOL bRet = FALSE; HWND hwnd = this->hwnd; HDC hdc; TEXTMETRIC tm; RECT rcT; LOGFONT lf;
this->lStyle = GetWindowLong(hwnd, GWL_STYLE); RecAct_SetColors(this);
// Determine some font things
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE); this->hfont = CreateFontIndirect(&lf);
// This window is registered with the CS_OWNDC flag
this->hdcOwn = GetDC(hwnd); ASSERT(this->hdcOwn);
hdc = this->hdcOwn;
SelectFont(hdc, this->hfont); GetTextMetrics(hdc, &tm); this->cyText = tm.tmHeight;
// Calculate text extent for sideitems (use the listbox font)
//
SetRectFromExtent(hdc, &rcT, c_szEllipses); this->cxEllipses = rcT.right - rcT.left;
SetRectFromExtent(hdc, &rcT, c_szDateDummy); this->cxSideItem = (rcT.right - rcT.left) + 2*g_cxMargin;
// Create windows used by control
if (RecAct_CreateWindows(this, lpcs)) { RecAct_CalcCoords(this);
this->lpfnLBProc = SubclassWindow(this->hwndLB, RecActLB_LBProc);
// Get the system imagelist cache
//
this->himlCache = ImageList_Create(g_cxIcon, g_cyIcon, TRUE, 8, 8); if (this->himlCache) { if (CreateImageList(&this->himlAction, hdc, IDB_ACTIONS, CX_ACTIONBMP, CY_ACTIONBMP, 8)) { SIZE size;
// Get some metrics
this->cxMenuCheck = GetSystemMetrics(SM_CXMENUCHECK); this->cyMenuCheck = GetSystemMetrics(SM_CYMENUCHECK);
size.cx = this->cxMenuCheck; size.cy = this->cyMenuCheck; this->hbmpBullet = CreateBulletBitmap(&size); if (this->hbmpBullet) { bRet = RecAct_CreateMenu(this); } } } }
return bRet; }
/*----------------------------------------------------------
Purpose: WM_DESTROY Handler Returns: -- Cond: -- */ void PRIVATE RecAct_OnDestroy( LPRECACT this) { if (this->himlCache) { ImageList_Destroy(this->himlCache); this->himlCache = NULL; }
if (this->himlAction) { ImageList_Destroy(this->himlAction); this->himlAction = NULL; } if (this->hbmpBullet) { DeleteBitmap(this->hbmpBullet); this->hbmpBullet = NULL; }
if (this->hmenu) { DestroyMenu(this->hmenu); this->hmenu = NULL; }
if (this->hbrBkgnd) DeleteBrush(this->hbrBkgnd);
if (this->hfont) DeleteFont(this->hfont); }
/*----------------------------------------------------------
Purpose: WM_COMMAND Handler Returns: -- Cond: -- */ VOID PRIVATE RecAct_OnCommand( LPRECACT this, int id, HWND hwndCtl, UINT uNotifyCode) { if (hwndCtl == this->hwndLB) { switch (uNotifyCode) { case LBN_SELCHANGE: break; } } }
/*----------------------------------------------------------
Purpose: WM_NOTIFY handler Returns: varies Cond: -- */ LRESULT PRIVATE RecAct_OnNotify( LPRECACT this, int idFrom, NMHDR FAR * lpnmhdr) { LRESULT lRet = 0;
switch (lpnmhdr->code) { case HDN_BEGINTRACK: lRet = TRUE; // prevent tracking
break;
default: break; }
return lRet; }
/*----------------------------------------------------------
Purpose: WM_CONTEXTMENU handler Returns: -- Cond: -- */ void PRIVATE RecAct_OnContextMenu( LPRECACT this, HWND hwnd, int x, int y) { if (hwnd == this->hwndLB) { POINT pt; int iHitEntry; BOOL bHelpOnly = TRUE; pt.x = x; pt.y = y; ScreenToClient(hwnd, &pt); iHitEntry = (pt.y / ListBox_GetItemHeight(hwnd, 0)) + ListBox_GetTopIndex(hwnd);
ASSERT(iHitEntry >= 0); if (iHitEntry < ListBox_GetCount(hwnd)) { ListBox_SetCurSel(hwnd, iHitEntry); ListBox_RepaintItemNow(hwnd, iHitEntry, NULL, FALSE);
bHelpOnly = FALSE; }
// Bring up the context menu for the listbox
RecAct_DoContextMenu(this, x, y, iHitEntry, bHelpOnly); } }
/*----------------------------------------------------------
Purpose: Calculate the rectangle boundary of a sideitem
Returns: calculated rect Cond: -- */ void PRIVATE RecAct_CalcSideItemRect( LPRECACT this, int nSide, // SIDE_INSIDE or SIDE_OUTSIDE
LPRECT prcOut) { int x; int y = g_cyIconMargin*2;
if (SIDE_INSIDE == nSide) { x = g_cxMargin; if ( !RecAct_IsNoIcon(this) ) x += X_INCOLUMN; } else { ASSERT(SIDE_OUTSIDE == nSide); x = this->cxItem - this->cxSideItem - g_cxMargin; }
prcOut->left = x; prcOut->top = y; prcOut->right = x + this->cxSideItem; prcOut->bottom = y + (this->cyText * 3); }
/*----------------------------------------------------------
Purpose: Draw a reconciliation listbox entry Returns: -- Cond: -- */ void PRIVATE RecAct_RecomputeItemMetrics( LPRECACT this, LPRA_PRIV ppriv) { HDC hdc = this->hdcOwn; LPDOBJ pdobj = ppriv->rgdobj; RECT rcT; RECT rcUnion; char szIDS[MAXBUFLEN]; UINT ids; int cyText = this->cyText; POINT pt;
// Compute the metrics and dimensions of each of the draw objects
// and store back into the item.
// File icon and label
pt.x = 0; pt.y = 0; ComputeImageRects(FIGetDisplayName(ppriv->pfi), hdc, &pt, &pdobj->rcBounding, &pdobj->rcLabel, g_cxIcon, g_cyIcon, g_cxIconSpacing, cyText);
pdobj->uKind = DOK_IMAGE; pdobj->lpvObject = FIGetDisplayName(ppriv->pfi); pdobj->uFlags = DOF_DIFFER | DOF_CENTER; if (RecAct_IsNoIcon(this)) SetFlag(pdobj->uFlags, DOF_NODRAW); pdobj->x = pt.x; pdobj->y = pt.y; pdobj->himl = this->himlCache; pdobj->iImage = (UINT)ppriv->pfi->lParam;
rcUnion = pdobj->rcBounding;
// Sideitem Info (Inside Briefcase)
RecAct_CalcSideItemRect(this, SIDE_INSIDE, &rcT);
pdobj++; pdobj->uKind = DOK_SIDEITEM; pdobj->lpvObject = &ppriv->siInside; pdobj->uFlags = DOF_LEFT; pdobj->x = rcT.left; pdobj->y = rcT.top; pdobj->rcClip = rcT; pdobj->rcBounding = rcT;
// Sideitem Info (Outside Briefcase)
RecAct_CalcSideItemRect(this, SIDE_OUTSIDE, &rcT);
pdobj++; pdobj->uKind = DOK_SIDEITEM; pdobj->lpvObject = &ppriv->siOutside; pdobj->uFlags = DOF_LEFT; pdobj->x = rcT.left; pdobj->y = rcT.top; pdobj->rcClip = rcT; pdobj->rcBounding = rcT;
UnionRect(&rcUnion, &rcUnion, &rcT);
// Action image
ASSERT(ppriv->uAction <= ARRAYSIZE(c_mpraiaiImage));
pdobj++;
ids = GetActionText(ppriv); pt.x = this->xAction; pt.y = 0; ComputeImageRects(SzFromIDS(ids, szIDS, sizeof(szIDS)), hdc, &pt, &pdobj->rcBounding, &pdobj->rcLabel, CX_ACTIONBMP, CY_ACTIONBMP, this->cxAction, cyText);
pdobj->uKind = DOK_IMAGE; pdobj->lpvObject = (LPVOID)ids; pdobj->uFlags = DOF_CENTER | DOF_USEIDS; if (!RecAct_IsNoIcon(this)) SetFlag(pdobj->uFlags, DOF_IGNORESEL); pdobj->x = pt.x; pdobj->y = pt.y; pdobj->himl = this->himlAction; pdobj->iImage = c_mpraiaiImage[ppriv->uAction];
UnionRect(&rcUnion, &rcUnion, &pdobj->rcBounding);
// Set the bounding rect of this item.
ppriv->cx = rcUnion.right - rcUnion.left; ppriv->cy = max((rcUnion.bottom - rcUnion.top), g_cyIconSpacing); }
/*----------------------------------------------------------
Purpose: WM_MEASUREITEM handler Returns: -- Cond: -- */ void PRIVATE RecAct_OnMeasureItem( LPRECACT this, LPMEASUREITEMSTRUCT lpmis) { HDC hdc = this->hdcOwn;
switch (lpmis->CtlType) { case ODT_LISTBOX: { LPRA_PRIV ppriv = (LPRA_PRIV)lpmis->itemData; // Recompute item metrics?
if (RECOMPUTE == ppriv->cx) { RecAct_RecomputeItemMetrics(this, ppriv); // Yes
}
lpmis->itemHeight = ppriv->cy; } break;
case ODT_MENU: { int i; int cxMac = 0; RECT rc; char sz[MAXBUFLEN];
// Calculate based on font and image dimensions.
//
SelectFont(hdc, this->hfont);
cxMac = 0; for (i = 0; i < ARRAYSIZE(c_rgramid); i++) { SzFromIDS(c_rgramid[i].ids, sz, sizeof(sz)); SetRectFromExtent(hdc, &rc, sz); cxMac = max(cxMac, g_cxMargin + CX_ACTIONBMP + g_cxMargin + (rc.right-rc.left) + g_cxMargin); }
lpmis->itemHeight = max(this->cyText, CY_ACTIONBMP); lpmis->itemWidth = cxMac; } break; } }
/*----------------------------------------------------------
Purpose: Draw a reconciliation listbox entry Returns: -- Cond: -- */ void PRIVATE RecAct_DrawLBItem( LPRECACT this, const DRAWITEMSTRUCT FAR * lpcdis) { LPRA_PRIV ppriv = (LPRA_PRIV)lpcdis->itemData; HDC hdc = lpcdis->hDC; RECT rc = lpcdis->rcItem; POINT ptSav; LPDOBJ pdobj; UINT cdobjs;
if (!ppriv) { // Empty listbox and we're getting the focus
return; }
SetBkMode(hdc, TRANSPARENT); // required for Shell_DrawText
SetViewportOrgEx(hdc, rc.left, rc.top, &ptSav);
// The Chicago-look mandates that icon and filename are selected,
// the rest of the entry is normal. Yuk.
// Recompute item metrics?
if (RECOMPUTE == ppriv->cx) { RecAct_RecomputeItemMetrics(this, ppriv); // Yes
}
// Do we need to redraw everything?
if (IsFlagSet(lpcdis->itemAction, ODA_DRAWENTIRE)) { // Yes
cdobjs = ARRAYSIZE(ppriv->rgdobj); pdobj = ppriv->rgdobj; } else { // No; should we even draw the file icon or action icon?
if (lpcdis->itemAction & (ODA_FOCUS | ODA_SELECT)) { cdobjs = 1; // Yes
// Focus rect on file icon?
if (!RecAct_IsNoIcon(this)) pdobj = ppriv->rgdobj; else pdobj = &ppriv->rgdobj[IDOBJ_ACTION]; } else { cdobjs = 0; // No
pdobj = ppriv->rgdobj; } }
Dobj_Draw(hdc, pdobj, cdobjs, lpcdis->itemState, this->cxEllipses, this->cyText, this->clrBkgnd); // Clean up
//
SetViewportOrgEx(hdc, ptSav.x, ptSav.y, NULL); }
/*----------------------------------------------------------
Purpose: Draw an action menu item Returns: -- Cond: -- */ void PRIVATE RecAct_DrawMenuItem( LPRECACT this, const DRAWITEMSTRUCT FAR * lpcdis) { LPRAMID pramid = (LPRAMID)lpcdis->itemData; HDC hdc = lpcdis->hDC; RECT rc = lpcdis->rcItem; DOBJ dobj; LPDOBJ pdobj; POINT ptSav; MENUITEMINFO mii; int cx; int cy; UINT uFlags; UINT uFlagsChecked;
ASSERT(pramid); if (lpcdis->itemID == -1) return;
SetViewportOrgEx(hdc, rc.left, rc.top, &ptSav); OffsetRect(&rc, -rc.left, -rc.top);
cx = rc.right - rc.left; cy = rc.bottom - rc.top;
// Get the menu state
mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE | MIIM_CHECKMARKS; GetMenuItemInfo(this->hmenu, lpcdis->itemID, FALSE, &mii); uFlagsChecked = IsFlagClear(mii.fState, MFS_CHECKED) ? DOF_NODRAW : 0;
uFlags = DOF_DIFFER | DOF_MENU | DOF_USEIDS; if (IsFlagSet(mii.fState, MFS_GRAYED)) SetFlag(uFlags, DOF_DISABLED);
// Build the array of DObjs that we want to draw.
// Action image
pdobj = &dobj;
pdobj->uKind = DOK_IMAGE; pdobj->lpvObject = (LPVOID)pramid->ids; pdobj->himl = this->himlAction; pdobj->iImage = pramid->iImage; pdobj->uFlags = uFlags; pdobj->x = g_cxMargin; pdobj->y = (cy - CY_ACTIONBMP) / 2; pdobj->rcLabel.left = 0; pdobj->rcLabel.right = cx; pdobj->rcLabel.top = 0; pdobj->rcLabel.bottom = cy;
// Draw the entry...
//
Dobj_Draw(hdc, &dobj, 1, lpcdis->itemState, 0, this->cyText, this->clrBkgnd); // Clean up
//
SetViewportOrgEx(hdc, ptSav.x, ptSav.y, NULL); }
/*----------------------------------------------------------
Purpose: WM_DRAWITEM handler Returns: -- Cond: -- */ void PRIVATE RecAct_OnDrawItem( LPRECACT this, const DRAWITEMSTRUCT FAR * lpcdis) { switch (lpcdis->CtlType) { case ODT_LISTBOX: RecAct_DrawLBItem(this, lpcdis); break;
case ODT_MENU: RecAct_DrawMenuItem(this, lpcdis); break; } }
/*----------------------------------------------------------
Purpose: WM_COMPAREITEM handler Returns: -1 (item 1 precedes item 2), 0 (equal), 1 (item 2 precedes item 1) Cond: -- */ int PRIVATE RecAct_OnCompareItem( LPRECACT this, const COMPAREITEMSTRUCT FAR * lpcis) { LPRA_PRIV ppriv1 = (LPRA_PRIV)lpcis->itemData1; LPRA_PRIV ppriv2 = (LPRA_PRIV)lpcis->itemData2;
// We sort based on name of file
//
return lstrcmpi(FIGetPath(ppriv1->pfi), FIGetPath(ppriv2->pfi)); }
/*----------------------------------------------------------
Purpose: WM_DELETEITEM handler Returns: -- Cond: -- */ void RecAct_OnDeleteLBItem( LPRECACT this, const DELETEITEMSTRUCT FAR * lpcdis) { switch (lpcdis->CtlType) { case ODT_LISTBOX: { LPRA_PRIV ppriv = (LPRA_PRIV)lpcdis->itemData; ASSERT(ppriv); if (ppriv) { FIFree(ppriv->pfi);
GFree(ppriv->siInside.pszDir); GFree(ppriv->siOutside.pszDir); GFree(ppriv); } } break; } }
/*----------------------------------------------------------
Purpose: WM_CTLCOLORLISTBOX handler Returns: -- Cond: -- */ HBRUSH PRIVATE RecAct_OnCtlColorListBox( LPRECACT this, HDC hdc, HWND hwndLB, int nType) { return this->hbrBkgnd; }
/*----------------------------------------------------------
Purpose: WM_PAINT handler Returns: -- Cond: -- */ void RecAct_OnPaint( LPRECACT this) { HWND hwnd = this->hwnd; PAINTSTRUCT ps; RECT rc; HDC hdc;
hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rc); if (IsFlagSet(this->lStyle, RAS_SINGLEITEM)) { DrawEdge(hdc, &rc, BDR_SUNKENINNER, BF_TOPLEFT); DrawEdge(hdc, &rc, BDR_SUNKENOUTER, BF_BOTTOMRIGHT); } else { DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT); }
EndPaint(hwnd, &ps); }
/*----------------------------------------------------------
Purpose: WM_SETFONT handler Returns: -- Cond: -- */ void RecAct_OnSetFont( LPRECACT this, HFONT hfont, BOOL bRedraw) { this->hfont = hfont; FORWARD_WM_SETFONT(this->hwnd, hfont, bRedraw, RecAct_DefProc); }
/*----------------------------------------------------------
Purpose: WM_SETFOCUS handler Returns: -- Cond: -- */ void RecAct_OnSetFocus( LPRECACT this, HWND hwndOldFocus) { SetFocus(this->hwndLB); }
/*----------------------------------------------------------
Purpose: WM_SYSCOLORCHANGE handler Returns: -- Cond: -- */ void RecAct_OnSysColorChange( LPRECACT this) { RecAct_SetColors(this); InvalidateRect(this->hwnd, NULL, TRUE); }
/*----------------------------------------------------------
Purpose: Insert item Returns: index Cond: -- */ int PRIVATE RecAct_OnInsertItem( LPRECACT this, const LPRA_ITEM pitem) { HWND hwndLB = this->hwndLB; LPRA_PRIV pprivNew; char szPath[MAXPATHLEN]; int iRet = -1; int iItem = LB_ERR;
ASSERT(pitem); ASSERT(pitem->siInside.pszDir); ASSERT(pitem->siOutside.pszDir); ASSERT(pitem->pszName);
pprivNew = GAlloc(sizeof(*pprivNew)); if (pprivNew) { SetWindowRedraw(hwndLB, FALSE);
// Fill the prerequisite fields first
//
pprivNew->uStyle = pitem->uStyle; pprivNew->uAction = pitem->uAction;
// Set the fileinfo stuff and large icon system-cache index.
// If we can't get the fileinfo of the inside file, get the outside
// file. If neither can be found, then we fail
//
lstrcpy(szPath, pitem->siInside.pszDir); if (IsFlagClear(pitem->uStyle, RAIS_FOLDER)) PathAppend(szPath, pitem->pszName); PathMakePresentable(szPath);
if (FAILED(FICreate(szPath, &pprivNew->pfi, FIF_ICON))) { // Try the outside file
//
lstrcpy(szPath, pitem->siOutside.pszDir); if (IsFlagClear(pitem->uStyle, RAIS_FOLDER)) PathAppend(szPath, pitem->pszName); PathMakePresentable(szPath);
if (FAILED(FICreate(szPath, &pprivNew->pfi, FIF_ICON))) { // Don't try to touch the file
if (FAILED(FICreate(szPath, &pprivNew->pfi, FIF_ICON | FIF_DONTTOUCH))) goto Insert_Cleanup; } } ASSERT(pprivNew->pfi);
pprivNew->pfi->lParam = (LPARAM)ImageList_AddIcon(this->himlCache, pprivNew->pfi->hicon);
// Fill in the rest of the fields
//
lstrcpy(szPath, pitem->siInside.pszDir); if (IsFlagSet(pitem->uStyle, RAIS_FOLDER)) PathRemoveFileSpec(szPath); PathMakePresentable(szPath); if (!GSetString(&pprivNew->siInside.pszDir, szPath)) goto Insert_Cleanup;
pprivNew->siInside.uState = pitem->siInside.uState; pprivNew->siInside.fs = pitem->siInside.fs;
lstrcpy(szPath, pitem->siOutside.pszDir); if (IsFlagSet(pitem->uStyle, RAIS_FOLDER)) PathRemoveFileSpec(szPath); PathMakePresentable(szPath); if (!GSetString(&pprivNew->siOutside.pszDir, szPath)) goto Insert_Cleanup;
pprivNew->siOutside.uState = pitem->siOutside.uState; pprivNew->siOutside.fs = pitem->siOutside.fs;
pprivNew->lParam = pitem->lParam;
pprivNew->cx = RECOMPUTE;
// We know we're doing a redundant sorted add if the element
// needs to be inserted at the end of the list, but who cares.
//
if (pitem->iItem >= RecAct_GetCount(this)) iItem = ListBox_AddString(hwndLB, pprivNew); else iItem = ListBox_InsertString(hwndLB, pitem->iItem, pprivNew); if (iItem == LB_ERR) goto Insert_Cleanup;
SetWindowRedraw(hwndLB, TRUE);
iRet = iItem; } goto Insert_End;
Insert_Cleanup: // Have DeleteString handler clean up field allocations
// of pitem.
//
if (iItem != LB_ERR) ListBox_DeleteString(hwndLB, iItem); else { FIFree(pprivNew->pfi); GFree(pprivNew); } SetWindowRedraw(hwndLB, TRUE); Insert_End:
return iRet; }
/*----------------------------------------------------------
Purpose: Delete item Returns: count of items left Cond: -- */ int PRIVATE RecAct_OnDeleteItem( LPRECACT this, int i) { HWND hwndLB = this->hwndLB; return ListBox_DeleteString(hwndLB, i); }
/*----------------------------------------------------------
Purpose: Delete all items Returns: TRUE Cond: -- */ BOOL PRIVATE RecAct_OnDeleteAllItems( LPRECACT this) { ListBox_ResetContent(this->hwndLB); return TRUE; }
/*----------------------------------------------------------
Purpose: Get item Returns: TRUE on success Cond: -- */ BOOL PRIVATE RecAct_OnGetItem( LPRECACT this, LPRA_ITEM pitem) { LPRA_PRIV ppriv; HWND hwndLB = this->hwndLB; UINT uMask; int iItem; if (!pitem) return FALSE; iItem = pitem->iItem; uMask = pitem->mask; ListBox_GetText(hwndLB, iItem, &ppriv); if (uMask & RAIF_ACTION) pitem->uAction = ppriv->uAction; if (uMask & RAIF_NAME) pitem->pszName = FIGetPath(ppriv->pfi); if (uMask & RAIF_STYLE) pitem->uStyle = ppriv->uStyle; if (uMask & RAIF_INSIDE) pitem->siInside = ppriv->siInside; if (uMask & RAIF_OUTSIDE) pitem->siOutside = ppriv->siOutside; if (uMask & RAIF_LPARAM) pitem->lParam = ppriv->lParam; return TRUE; }
/*----------------------------------------------------------
Purpose: Set item Returns: TRUE on success Cond: -- */ BOOL PRIVATE RecAct_OnSetItem( LPRECACT this, LPRA_ITEM pitem) { LPRA_PRIV ppriv; HWND hwndLB = this->hwndLB; UINT uMask; int iItem;
if (!pitem) return FALSE; uMask = pitem->mask; iItem = pitem->iItem; ListBox_GetText(hwndLB, iItem, &ppriv); if (uMask & RAIF_ACTION) ppriv->uAction = pitem->uAction; if (uMask & RAIF_STYLE) ppriv->uStyle = pitem->uStyle; if (uMask & RAIF_NAME) { if (!FISetPath(&ppriv->pfi, pitem->pszName, FIF_ICON)) return FALSE;
ppriv->pfi->lParam = (LPARAM)ImageList_AddIcon(this->himlCache, ppriv->pfi->hicon); } if (uMask & RAIF_INSIDE) { if (!GSetString(&ppriv->siInside.pszDir, pitem->siInside.pszDir)) return FALSE; ppriv->siInside.uState = pitem->siInside.uState; ppriv->siInside.fs = pitem->siInside.fs; } if (uMask & RAIF_OUTSIDE) { if (!GSetString(&ppriv->siOutside.pszDir, pitem->siOutside.pszDir)) return FALSE; ppriv->siOutside.uState = pitem->siOutside.uState; ppriv->siOutside.fs = pitem->siOutside.fs; } if (uMask & RAIF_LPARAM) ppriv->lParam = pitem->lParam; return TRUE; }
/*----------------------------------------------------------
Purpose: Get the current selection Returns: index Cond: -- */ int PRIVATE RecAct_OnGetCurSel( LPRECACT this) { return ListBox_GetCurSel(this->hwndLB); }
/*----------------------------------------------------------
Purpose: Set the current selection Returns: -- Cond: -- */ int PRIVATE RecAct_OnSetCurSel( LPRECACT this, int i) { int iRet = ListBox_SetCurSel(this->hwndLB, i);
if (iRet != LB_ERR) RecAct_SendSelChange(this, i);
return iRet; }
/*----------------------------------------------------------
Purpose: Find an item Returns: TRUE on success Cond: -- */ int PRIVATE RecAct_OnFindItem( LPRECACT this, int iStart, const RA_FINDITEM FAR * prafi) { HWND hwndLB = this->hwndLB; UINT uMask = prafi->flags; LPRA_PRIV ppriv; BOOL bPass; int i; int cItems = ListBox_GetCount(hwndLB);
for (i = iStart+1; i < cItems; i++) { bPass = TRUE; // assume we pass
ListBox_GetText(hwndLB, i, &ppriv);
if (uMask & RAFI_NAME && !IsSzEqual(FIGetPath(ppriv->pfi), prafi->psz)) bPass = FALSE;
if (uMask & RAFI_ACTION && ppriv->uAction != prafi->uAction) bPass = FALSE;
if (uMask & RAFI_LPARAM && ppriv->lParam != prafi->lParam) bPass = FALSE;
if (bPass) break; // found it
}
return i == cItems ? -1 : i; }
///////////////////////////////////////////////////// EXPORTED FUNCTIONS
/*----------------------------------------------------------
Purpose: RecAct window proc Returns: varies Cond: -- */ LRESULT CALLBACK RecAct_WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LPRECACT this = RecAct_GetPtr(hwnd); if (this == NULL) { if (msg == WM_NCCREATE) { this = GAlloc(sizeof(*this)); ASSERT(this); if (!this) return 0L; // OOM failure
this->hwnd = hwnd; RecAct_SetPtr(hwnd, this); } else { return RecAct_DefProc(hwnd, msg, wParam, lParam); } }
if (msg == WM_NCDESTROY) { GFree(this); RecAct_SetPtr(hwnd, NULL); }
switch (msg) { HANDLE_MSG(this, WM_CREATE, RecAct_OnCreate); HANDLE_MSG(this, WM_DESTROY, RecAct_OnDestroy); HANDLE_MSG(this, WM_SETFONT, RecAct_OnSetFont); HANDLE_MSG(this, WM_COMMAND, RecAct_OnCommand); HANDLE_MSG(this, WM_NOTIFY, RecAct_OnNotify); HANDLE_MSG(this, WM_MEASUREITEM, RecAct_OnMeasureItem); HANDLE_MSG(this, WM_DRAWITEM, RecAct_OnDrawItem); HANDLE_MSG(this, WM_COMPAREITEM, RecAct_OnCompareItem); HANDLE_MSG(this, WM_DELETEITEM, RecAct_OnDeleteLBItem); HANDLE_MSG(this, WM_CONTEXTMENU, RecAct_OnContextMenu); HANDLE_MSG(this, WM_SETFOCUS, RecAct_OnSetFocus); HANDLE_MSG(this, WM_CTLCOLORLISTBOX, RecAct_OnCtlColorListBox); HANDLE_MSG(this, WM_PAINT, RecAct_OnPaint); HANDLE_MSG(this, WM_SYSCOLORCHANGE, RecAct_OnSysColorChange);
case RAM_GETITEMCOUNT: return (LRESULT)RecAct_GetCount(this);
case RAM_GETITEM: return (LRESULT)RecAct_OnGetItem(this, (LPRA_ITEM)lParam);
case RAM_SETITEM: return (LRESULT)RecAct_OnSetItem(this, (const LPRA_ITEM)lParam);
case RAM_INSERTITEM: return (LRESULT)RecAct_OnInsertItem(this, (const LPRA_ITEM)lParam);
case RAM_DELETEITEM: return (LRESULT)RecAct_OnDeleteItem(this, (int)wParam);
case RAM_DELETEALLITEMS: return (LRESULT)RecAct_OnDeleteAllItems(this);
case RAM_GETCURSEL: return (LRESULT)RecAct_OnGetCurSel(this);
case RAM_SETCURSEL: return (LRESULT)RecAct_OnSetCurSel(this, (int)wParam);
case RAM_FINDITEM: return (LRESULT)RecAct_OnFindItem(this, (int)wParam, (const RA_FINDITEM FAR *)lParam);
case RAM_REFRESH: RedrawWindow(this->hwndLB, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
default: return RecAct_DefProc(hwnd, msg, wParam, lParam); } }
///////////////////////////////////////////////////// PUBLIC FUNCTIONS
/*----------------------------------------------------------
Purpose: Initialize the reconciliation-action window class Returns: TRUE on success Cond: -- */ BOOL PUBLIC RecAct_Init(HINSTANCE hinst) { WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_DBLCLKS | CS_OWNDC; wc.lpfnWndProc = RecAct_WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LPRECACT); wc.hInstance = hinst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground= NULL; wc.lpszMenuName = NULL; wc.lpszClassName= WC_RECACT; wc.hIconSm = NULL;
return (RegisterClassEx(&wc) != 0); }
/*----------------------------------------------------------
Purpose: Clean up RecAct window class Returns: -- Cond: -- */ void PUBLIC RecAct_Term( HINSTANCE hinst) { UnregisterClass(WC_RECACT, hinst); }
/*----------------------------------------------------------
Purpose: Special sub-class listbox proc Returns: varies Cond: -- */ LRESULT _export CALLBACK RecActLB_LBProc( HWND hwnd, // window handle
UINT msg, // window message
WPARAM wparam, // varies
LPARAM lparam) // varies
{ LRESULT lRet; LPRECACT lpra = NULL;
// Get the instance data for the control
lpra = RecAct_GetPtr(GetParent(hwnd)); ASSERT(lpra);
switch (msg) { default: lRet = RecActLB_DefProc(lpra->lpfnLBProc, hwnd, msg, wparam, lparam); break; }
return lRet; }
|