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.
 
 
 
 
 
 

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;
}