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.
518 lines
11 KiB
518 lines
11 KiB
/*
|
|
* CSTATHLP.CPP
|
|
*
|
|
* CStatusHelper class to assist managing the strings for the
|
|
* status bar. Here we provide menu ID to string ID mapping
|
|
* services using a mapping structure in the module's resources.
|
|
*
|
|
* This code assumes that the status bar is a standard Windows
|
|
* status bar control as we use SetWindowText (WM_SETTEXT) to set
|
|
* strings. This displays messages in the 0th pane of the bar,
|
|
* which is all we need.
|
|
*
|
|
* with SCC Changes for SCC QuickView - SDN
|
|
*/
|
|
|
|
|
|
#include <windows.h>
|
|
#include "cstrtabl.h"
|
|
#include "cstathlp.h"
|
|
#include "resource.h"
|
|
|
|
|
|
/*
|
|
* CStatusHelper::CStatusHelper
|
|
* CStatusHelper::~CStatusHelper
|
|
*
|
|
* Constructor Parameters:
|
|
* hWnd HWND of the Status Bar control to work with.
|
|
* hInst HINSTANCE of the module we're in.
|
|
*/
|
|
|
|
CStatusHelper::CStatusHelper(HWND hWnd, HINSTANCE hInst)
|
|
{
|
|
m_hWnd=hWnd;
|
|
m_hInst=hInst;
|
|
|
|
m_uIDCur=0xFFFFFFFF; //Nothing shown yet.
|
|
|
|
m_pST=NULL;
|
|
m_pPMM=NULL;
|
|
m_pSMM=NULL;
|
|
m_hMemSMM=NULL;
|
|
|
|
//With this FALSE, many other members are ignored.
|
|
m_fMapped=FALSE;
|
|
}
|
|
|
|
|
|
|
|
CStatusHelper::~CStatusHelper(void)
|
|
{
|
|
//Free up anything from MessageMap
|
|
if (NULL!=m_pPMM)
|
|
{
|
|
LocalFree((HLOCAL)m_pPMM);
|
|
m_pPMM=NULL;
|
|
}
|
|
|
|
if (NULL!=m_pST)
|
|
{
|
|
delete m_pST;
|
|
m_pST=NULL;
|
|
}
|
|
|
|
if (NULL!=m_pNewSMM)
|
|
{
|
|
// UnlockResource(m_hMemSMM);
|
|
LocalFree ((HLOCAL)m_pNewSMM);
|
|
m_pNewSMM = NULL;
|
|
m_pSMM=NULL;
|
|
}
|
|
|
|
if (NULL!=m_hMemSMM)
|
|
{
|
|
//FreeResource(m_hMemSMM);
|
|
m_hMemSMM=NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::MessageMap
|
|
*
|
|
* Purpose:
|
|
* Initializes a CStatusHelper for automated processing of
|
|
* WM_MENUSELECT messages as well as setting up a list of messages
|
|
* that we can display using identifiers instead of string
|
|
* pointers. See MenuSelect and MessageDisplay members.
|
|
*
|
|
* This function is the initializer for the CStatusHelper class.
|
|
* If it fails, then the caller should delete the object.
|
|
*
|
|
* Parameters:
|
|
* hWndOwner HWND of the window owning menus we're
|
|
* interested in serving
|
|
* uIDRMap UINT identifying a resource mapping ID values
|
|
* to string ID values
|
|
* idsMin UINT specifying the lowest string ID to load
|
|
* idsMax UINT specifying the hightest string ID to load
|
|
* cchMax UINT maximum string length
|
|
* uIDPopupMin UINT of the lowest ID to assign to popup menus
|
|
* uIDPopupMax UINT of the highest ID to assign to popup menus
|
|
* uIDStatic UINT of the ID for the quiescent state message
|
|
* uIDBlank UINT of the ID for a blank message
|
|
* uIDSysMenu UINT of the ID for the system menu
|
|
*
|
|
* Return Value:
|
|
* BOOL TRUE if the function was successful,
|
|
* FALSE otherwise.
|
|
*/
|
|
|
|
BOOL CStatusHelper::MessageMap(HWND hWndOwner, UINT uIDRMap
|
|
, UINT idsMin, UINT idsMax, UINT cchMax, UINT uIDPopupMin
|
|
, UINT uIDPopupMax, UINT uIDStatic, UINT uIDBlank, UINT uIDSysMenu)
|
|
{
|
|
// HMENU hMenu;
|
|
HRSRC hRes;
|
|
UINT i;
|
|
// USHORT uID;
|
|
DWORD locSize;
|
|
|
|
/*
|
|
* Check if we even got a valid window in the constructor
|
|
* or if we've already been called.
|
|
*/
|
|
if (!IsWindow(m_hWnd) || m_fMapped)
|
|
return FALSE;
|
|
|
|
//Parameter validation
|
|
if (idsMax < idsMin || uIDPopupMax < uIDPopupMin)
|
|
return FALSE;
|
|
|
|
//Cache away all this vital information
|
|
m_hWndOwner =hWndOwner;
|
|
m_idsMin =idsMin;
|
|
m_idsMax =idsMax;
|
|
m_cMessages =(USHORT)(idsMax-idsMin+1);
|
|
|
|
m_uIDPopupMin=uIDPopupMin;
|
|
m_uIDPopupMax=uIDPopupMax;
|
|
m_cPopups =(USHORT)(uIDPopupMax-uIDPopupMin+1);
|
|
|
|
m_uIDStatic =uIDStatic;
|
|
m_uIDBlank =uIDBlank;
|
|
m_uIDSysMenu =uIDSysMenu;
|
|
|
|
|
|
//Get a stringtable with all the messages
|
|
m_pST=new CStringTable(m_hInst);
|
|
|
|
if (NULL==m_pST)
|
|
return FALSE;
|
|
|
|
if (!m_pST->FInit(idsMin, idsMax, CCHSTATUSMSGMAX))
|
|
return FALSE;
|
|
|
|
|
|
//Load the STATMESSAGEMAP array from resources
|
|
hRes=FindResource(m_hInst, MAKEINTRESOURCE(uIDRMap), RT_RCDATA);
|
|
|
|
if (NULL==hRes)
|
|
return FALSE;
|
|
|
|
m_hMemSMM=LoadResource(m_hInst, hRes);
|
|
|
|
if (NULL==m_hMemSMM)
|
|
return FALSE;
|
|
|
|
m_pSMM=(PSTATMESSAGEMAP)LockResource(m_hMemSMM);
|
|
|
|
if (NULL==m_pSMM)
|
|
return FALSE;
|
|
|
|
locSize = SizeofResource(m_hInst, hRes);
|
|
if (locSize==0) locSize = 0x100;
|
|
|
|
m_pNewSMM = (PSTATMESSAGEMAP)LocalAlloc(LPTR,
|
|
locSize);
|
|
|
|
|
|
for (i=0; i<locSize; i++)
|
|
*((char*)m_pNewSMM+i) = *((char *)m_pSMM+i);
|
|
|
|
UnlockResource(m_hMemSMM);
|
|
FreeResource(m_hMemSMM);
|
|
m_hMemSMM=NULL;
|
|
|
|
//Sort these for binary search lookup.
|
|
Sort();
|
|
|
|
|
|
// //Allocate an array of POPUPMENUMAP structures
|
|
// m_pPMM=(PPOPUPMENUMAP)LocalAlloc(LPTR
|
|
// , sizeof(POPUPMENUMAP)*m_cPopups);
|
|
//
|
|
// if (NULL==m_pPMM)
|
|
// return FALSE;
|
|
//
|
|
// //Initialize the array mapping popup menus to specific IDs.
|
|
// uID=uIDPopupMin;
|
|
// hMenu=GetMenu(m_hWndOwner);
|
|
//
|
|
// for (i=0; i < m_cPopups; i++)
|
|
// {
|
|
// m_pPMM[i].hMenu=GetSubMenu(hMenu, i);
|
|
// m_pPMM[i].uID =uID++;
|
|
// }
|
|
|
|
//All done!
|
|
m_fMapped=TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::MenuSelect
|
|
*
|
|
* Purpose:
|
|
* Displays the appropriate message for whatever is in the
|
|
* parameters of a WM_MENUSELECT message. This can only be called
|
|
* if StatStripMessageMap has already been called and must be used
|
|
* with the same menu the owner window had at the time of that call.
|
|
*
|
|
* Parameters:
|
|
* wItem WORD identifying the selected item
|
|
* wFlags WORD specifying the type of menu item
|
|
* hMenu HMENU of the menu selected.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void CStatusHelper::MenuSelect(WORD wItem, WORD wFlags, HMENU hMenu)
|
|
{
|
|
USHORT uID;
|
|
|
|
if (!m_fMapped)
|
|
return;
|
|
|
|
//Case 1: Menu was cancelled, display static string
|
|
if (0==wItem && (WORD)0xFFFF==wFlags)
|
|
uID=m_uIDStatic;
|
|
else
|
|
{
|
|
//Case 2: System menu selected by itself.
|
|
if ((MF_POPUP & wFlags) && (MF_SYSMENU & wFlags))
|
|
uID=m_uIDSysMenu;
|
|
else
|
|
{
|
|
/*
|
|
* Case 3: A popup menu was chosen:
|
|
* Find the ID for the popup menu index in wItem
|
|
*/
|
|
if (MF_POPUP & wFlags)
|
|
uID=IDFromHMenu((HMENU)wItem);
|
|
else if (MFT_SEPARATOR & wFlags)
|
|
uID=(UINT)wItem;
|
|
else
|
|
//Case 4: A menu item is selected
|
|
if ( (0!=wItem) && (-1!=wItem) )
|
|
uID=(UINT)wItem;
|
|
else
|
|
//Case 5: Nothing is selected (e.g. separator)
|
|
uID=m_uIDBlank;
|
|
}
|
|
}
|
|
|
|
//Display the message
|
|
MessageDisplay(uID);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::MessageDisplay
|
|
*
|
|
* Purpose:
|
|
* Displays the appropriate message for a given ID value. This
|
|
* can only be called if MessageMap has already been called.
|
|
*
|
|
* Parameters:
|
|
* uID UINT of the message to display. This is not
|
|
* a string ID but an ID in the STATMESSAGEMAP
|
|
* structure that maps to a string ID.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void CStatusHelper::MessageDisplay(UINT uID)
|
|
{
|
|
UINT idsMsg;
|
|
|
|
if (!m_fMapped)
|
|
return;
|
|
|
|
//If we're already displaying this ID, nothing we need to do
|
|
if (m_uIDCur==uID)
|
|
return;
|
|
|
|
//Go look up the string ID to display.
|
|
idsMsg=IStringFromID(uID);
|
|
|
|
//Display it.
|
|
SetWindowText(m_hWnd, (*m_pST)[idsMsg]);
|
|
m_uIDCur = uID;
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| CStatusHelper::Append (UINT uID, LPSTR lpStr)
|
|
|
|
|
*/
|
|
|
|
BOOL CStatusHelper::Append (UINT uID, LPSTR lpStr)
|
|
{
|
|
/* Given an ID, add the lpstr to the entry indexed by uID */
|
|
/* To be used for adding the APPNAME to the msg strings.. */
|
|
|
|
if (NULL==m_pST)
|
|
return FALSE;
|
|
|
|
return m_pST->Append (uID, lpStr);
|
|
}
|
|
|
|
/*
|
|
|
|
|
| CStatusHelper::Replace (UINT uID, LPSTR lpStr)
|
|
|
|
|
*/
|
|
|
|
BOOL CStatusHelper::Replace (UINT uID, LPSTR lpStr)
|
|
{
|
|
/* Given an ID, add the lpstr to the entry indexed by uID */
|
|
/* To be used for adding the APPNAME to the msg strings.. */
|
|
|
|
if (NULL==m_pST)
|
|
return FALSE;
|
|
|
|
return m_pST->Replace (uID, lpStr);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
** Private members follow.
|
|
**/
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::Sort
|
|
* (Private)
|
|
*
|
|
* Purpose:
|
|
* Performs a selection sort on the STATMESSAGEMAP array that we
|
|
* load from resources. Since we expect that the data is partially
|
|
* sorted (we tend to place things in resources in groups of
|
|
* seqential values), since the number of messages is usually
|
|
* less than 200, and since we're usually doing this stuff on startup
|
|
* (which takes a long time anyway), a cimple selection sort is a
|
|
* better choice than a more complex qsort.
|
|
*
|
|
* Parameters:
|
|
* None
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void CStatusHelper::Sort(void)
|
|
{
|
|
UINT i, j, k;
|
|
STATMESSAGEMAP smm;
|
|
|
|
for (j=0; j < (UINT)(m_cMessages-1); j++)
|
|
{
|
|
k=j;
|
|
smm.uID =m_pNewSMM[j].uID;
|
|
smm.idsMsg=m_pNewSMM[j].idsMsg;
|
|
|
|
for (i=j+1; i < (UINT)m_cMessages; i++)
|
|
{
|
|
if (m_pNewSMM[i].uID < smm.uID)
|
|
{
|
|
smm.uID =m_pNewSMM[i].uID;
|
|
smm.idsMsg=m_pNewSMM[i].idsMsg;
|
|
k=i;
|
|
}
|
|
}
|
|
|
|
smm.uID =m_pNewSMM[j].uID;
|
|
smm.idsMsg =m_pNewSMM[j].idsMsg;
|
|
m_pNewSMM[j].uID =m_pNewSMM[k].uID; ;
|
|
m_pNewSMM[j].idsMsg=m_pNewSMM[k].idsMsg;;
|
|
m_pNewSMM[k].uID =smm.uID;
|
|
m_pNewSMM[k].idsMsg=smm.idsMsg;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::IDFromHMenu
|
|
* (Private)
|
|
*
|
|
* Purpose:
|
|
* Given a specific popup menu index, searches through m_pPMM for
|
|
* a match and returns the ID associated with that menu.
|
|
*
|
|
* Parameters:
|
|
* hMenu HMENU to of he popup menu.
|
|
*
|
|
* Return Value:
|
|
* USHORT ID associated with the menu handle.
|
|
*/
|
|
|
|
USHORT CStatusHelper::IDFromHMenu(HMENU hMenu)
|
|
{
|
|
USHORT uID=m_uIDBlank; //Default is empty
|
|
UINT i;
|
|
|
|
i = (UINT) hMenu;
|
|
switch ( i )
|
|
{
|
|
case 0: //File
|
|
uID = IDM_FILE;
|
|
break;
|
|
case 1: //View
|
|
uID = IDM_VIEW;
|
|
break;
|
|
case 2: // Help
|
|
uID = IDM_HELP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// for (i=0; i < m_cPopups; i++)
|
|
// {
|
|
// if (m_pPMM[i].hMenu==hMenu)
|
|
// {
|
|
// uID=m_pPMM[i].uID;
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
return uID;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CStatusHelper::IStringFromID
|
|
* (Private)
|
|
*
|
|
* Purpose:
|
|
* Performs a binary search in a STATMESSAGEMAP array looking for
|
|
* a specific item ID returning the string ID for that item.
|
|
*
|
|
* Parameters:
|
|
* uID USHORT item ID to locate.
|
|
*
|
|
* Return Value:
|
|
* UINT String ID associated with wItem.
|
|
*/
|
|
|
|
UINT CStatusHelper::IStringFromID(USHORT uID)
|
|
{
|
|
UINT iLow =0;
|
|
UINT iHigh=m_cMessages-1;
|
|
UINT iMid;
|
|
|
|
while (TRUE)
|
|
{
|
|
iMid=(iLow+iHigh) >> 1;
|
|
|
|
if (uID < m_pNewSMM[iMid].uID)
|
|
iHigh=iMid-1;
|
|
else
|
|
{
|
|
if (uID > m_pNewSMM[iMid].uID)
|
|
iLow=iMid+1;
|
|
else
|
|
break; //Equality
|
|
}
|
|
|
|
if (iHigh < iLow)
|
|
break;
|
|
}
|
|
|
|
return m_pNewSMM[iMid].idsMsg;
|
|
}
|
|
|
|
|