// status bar class
// drawn in parent window rather than independant window
#include <mywin.h>
#pragma hdrstop
#include <string.h>
// status box **********************************************
StatusBox::StatusBox(char *T,int X,int W)
{
Text=strdup(T);
x=X; w=W;
}
StatusBox::~StatusBox()
{
if (Text) delete[] Text;
}
void StatusBox::SetText(char *T)
{
if (Text) delete[] Text;
Text=strdup(T);
}
// status bar **********************************************
// void Paint(HDC dc);
EV_START(StatusBar)
EV_MESSAGE(WM_KEYUP,WMKeyUp)
EV_MESSAGE(WM_KEYDOWN,WMKeyDown)
EV_MESSAGE(WM_SETFOCUS,WMFocus)
EV_MESSAGE(WM_SIZE,WMSize)
EV_MESSAGE(WM_GETMINMAXINFO,WMGetMinMaxInfo)
EV_MESSAGE(WM_MENUSELECT,WMMenuSelect)
EV_END
StatusBox *StatusBar::AddBox(char *T,int w)
{
StatusBox *S=new StatusBox(T,dyBorderx8 + Pos,w*CharWidth);
BoxList.AddTail(S);
Pos+=w*CharWidth+dyBorderx8;
return S;
}
void StatusBar::InsertBox(int After,char *T,int w)
{
StatusBox *Box=BoxList[After];
StatusBox *S=new StatusBox(T,Box->x+Box->w+dyBorderx8,w*CharWidth);
S->SetText(T);
BoxList.AddAfter(S,Box);
BoxList.GetNext(S);
while (S)
{
S->x+=w*CharWidth+dyBorderx8;
BoxList.GetNext(S);
}
DrawText(Box);
Invalidate();
}
StatusBar::StatusBar(Object *P,int w,BOOL NumBox,BOOL CapsBox) : Object(P)
{
dyBorder = GetSystemMetrics(SM_CYBORDER);
dyBorderx2 = dyBorder * 2;
dyBorderx3 = dyBorder * 3;
dyBorderx8 = dyBorder * 8;
dyBorderx9 = dyBorder * 9;
HDC dc = GetDC(NULL);
int Fntheight = MulDiv(-10, GetDeviceCaps(dc, LOGPIXELSY), 72);
Font = CreateFont(Fntheight, 0, 0, 0, 400, 0, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv");
SelectObject(dc, Font);
TEXTMETRIC tm;
GetTextMetrics(dc, &tm);
ReleaseDC(NULL, dc);
dyStatbar = tm.tmHeight + tm.tmExternalLeading + (7*dyBorder);
CharWidth = tm.tmMaxCharWidth;
Pos=0;
TextBox=AddBox("",w);
NumLock = NumBox ? AddBox("",3) : NULL;
CapsLock = CapsBox ? AddBox("",3) :NULL;
nMenu=0;
OldText=NULL;
}
StatusBar::~StatusBar()
{
if (OldText) delete[] OldText;
DeleteObject(Font);
}
BOOL StatusBar::SetupWindow()
{
nMenu=0;
ParsePopup(GetMenu(ParentHWnd));
return TRUE;
}
void StatusBar::SetText(char *T)
{
TextBox->SetText(T);
DrawText(TextBox);
}
void StatusBar::SetText(int Box,char *T)
{
StatusBox *S=BoxList[Box];
S->SetText(T);
DrawText(S);
}
void StatusBar::DrawText(StatusBox *S)
{
if (!S->Text) return;
RECT rc,rcTemp;
HDC dc = GetDC(ParentHWnd);
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
rcTemp.top = rc.top + dyBorder*4;
rcTemp.bottom = rc.bottom - dyBorderx3;
rcTemp.left = dyBorder + S->x;
rcTemp.right = rcTemp.left + S->w- dyBorder;
SelectObject(dc, Font);
SetTextColor(dc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, GetSysColor(COLOR_BTNFACE));
ExtTextOut(dc, rcTemp.left + dyBorderx2, rcTemp.top,
ETO_OPAQUE | ETO_CLIPPED, &rcTemp, S->Text,
strlen(S->Text), NULL);
ReleaseDC(ParentHWnd, dc);
}
void StatusBar::Paint(HDC dc)
{
RECT rc,rcTemp;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
/* Border color */
HBRUSH Brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
rcTemp = rc;
rcTemp.top += dyBorderx2;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* Shadow color */
Brush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
/* Top and left of boxes */
StatusBox *Ptr=BoxList.GetFirst();
while (Ptr)
{
rcTemp.top = rc.top + dyBorderx3;
rcTemp.bottom = rcTemp.top + dyBorder;
rcTemp.left = Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w;
FillRect(dc, &rcTemp, Brush);
rcTemp.bottom = rc.bottom - dyBorderx2;
rcTemp.right = rcTemp.left + dyBorder;
FillRect(dc, &rcTemp, Brush);
BoxList.GetNext(Ptr);
}
DeleteObject(Brush);
Brush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
/* Bottom and right of boxes */
Ptr=BoxList.GetFirst();
while (Ptr)
{
rcTemp.top = rc.bottom - dyBorderx3;
rcTemp.bottom = rcTemp.top + dyBorder;
rcTemp.left = Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w;
FillRect(dc, &rcTemp, Brush);
rcTemp.top = rc.top + dyBorderx3;
rcTemp.left = Ptr->x+Ptr->w;
rcTemp.right = rcTemp.left + dyBorder;
FillRect(dc, &rcTemp, Brush);
BoxList.GetNext(Ptr);
}
/* Across the top */
rcTemp = rc;
rcTemp.top += dyBorder;
rcTemp.bottom = rcTemp.top + dyBorder;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* solid black line across top */
Brush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
rcTemp = rc;
rcTemp.bottom = rcTemp.top;
rcTemp.bottom += dyBorder;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* now the text, with the button face background */
SelectObject(dc, Font);
SetTextColor(dc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, GetSysColor(COLOR_BTNFACE));
/* Text */
Ptr=BoxList.GetFirst();
while (Ptr)
{
if (Ptr->Text)
{
rcTemp.top = rc.top + dyBorder*4;
rcTemp.bottom = rc.bottom - dyBorderx3;
rcTemp.left = dyBorder + Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w - dyBorder;
ExtTextOut(dc, rcTemp.left + dyBorderx2, rcTemp.top,
ETO_OPAQUE | ETO_CLIPPED, &rcTemp, Ptr->Text,
strlen(Ptr->Text), NULL);
}
BoxList.GetNext(Ptr);
}
}
BOOL StatusBar::bInKeyDown=FALSE;
BOOL StatusBar::WMKeyUp(TMSG &)
{
bInKeyDown = FALSE;
return TRUE;
}
BOOL StatusBar::WMKeyDown(TMSG &Msg)
{
if ( !bInKeyDown )
{
if ( Msg.wParam == VK_CAPITAL ) SetCapsLockText();
else if ( Msg.wParam == VK_NUMLOCK ) SetNumLockText();
bInKeyDown = TRUE;
}
return TRUE;
}
BOOL StatusBar::WMFocus(TMSG &)
{
SetCapsLockText();
SetNumLockText();
return TRUE;
}
void StatusBar::SetNumLockText()
{
/* Num Lock Text */
if (NumLock)
{
int State=GetKeyState(VK_NUMLOCK) & 0x0001;
NumLock->SetText(State ? "NUM" : "");
DrawText(NumLock);
}
}
void StatusBar::SetCapsLockText()
{
/* Caps Lock Text */
if (CapsLock)
{
int State=GetKeyState(VK_CAPITAL) & 0x0001;
CapsLock->SetText(State ? "CAPS" : "");
DrawText(CapsLock);
}
}
void StatusBar::Invalidate()
{
RECT rc;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
InvalidateRect(ParentHWnd,&rc,TRUE);
}
BOOL StatusBar::WMSize(TMSG &)
{
RECT rc;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
if (rc.top < StatRecSizeAdv.top)
{
/* Window SHRANK, need to invalidate current status rect */
InvalidateRect(ParentHWnd, &rc,FALSE);
}
else
{
/* Window GREW, need to invalidate prev status rect */
InvalidateRect(ParentHWnd, &StatRecSizeAdv,TRUE);
}
return TRUE;
}
BOOL StatusBar::WMGetMinMaxInfo(TMSG &)
{
GetClientRect(ParentHWnd, &StatRecSizeAdv);
StatRecSizeAdv.top = StatRecSizeAdv.bottom - dyStatbar;
return TRUE;
}
#define NOMENU 0
// WM_MENUSELECT
BOOL StatusBar::WMMenuSelect(TMSG &Msg)
{
int nMenuID=NOMENU;
WORD flags=LLHW(Msg);
WORD item=LOWWPARAM(Msg.wParam);
if (HILP32(Msg) == NULL && flags == 0xffff)
{
// Exiting menu mode. hMenu && hmenuPopup are NULL.
//nMenuID = NOMENU;
if (OldText)
{
SetText(OldText);
delete[] OldText;
OldText=NULL;
}
return TRUE;
}
else if (flags & MF_SYSMENU)
{
// System menu is up
if (!(flags & MF_POPUP)) nMenuID = item;
// System menu item is selected
// System menu: item contains SC_* code.
else nMenuID = IDM_SYSMENU;
// System menu and no item is selected
}
else
{
if ((flags & MF_POPUP))
{
// Pulling down a popup submenu: hmenuPopup contains popup handle.
#ifdef WIN32
HMENU hm=GetSubMenu((HMENU) Msg.lParam,item);
for (int i=0;i<nMenu;i++)
if (hm==hMenu[i])
{
nMenuID=IDS_POPUP1+i;
break;
}
#else
for (int i=0;i<nMenu;i++)
if (item==hMenu[i])
{
nMenuID=IDS_POPUP1+i;
break;
}
#endif
}
else nMenuID = item;
}
//SetStatbarText(hwnd, nMenuID,TRUE);
char temp[255];
if ( LoadString(App::hInstance, nMenuID, temp, 255) == 0)
strcpy(temp,"");
if (!OldText) OldText=strdup(TextBox->Text ? TextBox->Text : ""); // null is reserved to indicate not in menu
SetText(temp);
return TRUE;
}
void StatusBar::ParsePopup(HMENU hm)
{
if (hm==NULL) return;
HMENU hm2;
int n=GetMenuItemCount(hm);
for (int i=0;i<n;i++)
{
hm2=GetSubMenu(hm,i);
if (hm2)
{
// add hm2 to hmenu list
hMenu[nMenu++]=hm2;
ParsePopup(hm2);
}
}
}
// status bar class
// drawn in parent window rather than independant window
#include <mywin.h>
#pragma hdrstop
#include <string.h>
// status box **********************************************
StatusBox::StatusBox(char *T,int X,int W)
{
Text=strdup(T);
x=X; w=W;
}
StatusBox::~StatusBox()
{
if (Text) delete[] Text;
}
void StatusBox::SetText(char *T)
{
if (Text) delete[] Text;
Text=strdup(T);
}
// status bar **********************************************
// void Paint(HDC dc);
EV_START(StatusBar)
EV_MESSAGE(WM_KEYUP,WMKeyUp)
EV_MESSAGE(WM_KEYDOWN,WMKeyDown)
EV_MESSAGE(WM_SETFOCUS,WMFocus)
EV_MESSAGE(WM_SIZE,WMSize)
EV_MESSAGE(WM_GETMINMAXINFO,WMGetMinMaxInfo)
EV_MESSAGE(WM_MENUSELECT,WMMenuSelect)
EV_END
StatusBox *StatusBar::AddBox(char *T,int w)
{
StatusBox *S=new StatusBox(T,dyBorderx8 + Pos,w*CharWidth);
BoxList.AddTail(S);
Pos+=w*CharWidth+dyBorderx8;
return S;
}
void StatusBar::InsertBox(int After,char *T,int w)
{
StatusBox *Box=BoxList[After];
StatusBox *S=new StatusBox(T,Box->x+Box->w+dyBorderx8,w*CharWidth);
S->SetText(T);
BoxList.AddAfter(S,Box);
BoxList.GetNext(S);
while (S)
{
S->x+=w*CharWidth+dyBorderx8;
BoxList.GetNext(S);
}
DrawText(Box);
Invalidate();
}
StatusBar::StatusBar(Object *P,int w,BOOL NumBox,BOOL CapsBox) : Object(P)
{
dyBorder = GetSystemMetrics(SM_CYBORDER);
dyBorderx2 = dyBorder * 2;
dyBorderx3 = dyBorder * 3;
dyBorderx8 = dyBorder * 8;
dyBorderx9 = dyBorder * 9;
HDC dc = GetDC(NULL);
int Fntheight = MulDiv(-10, GetDeviceCaps(dc, LOGPIXELSY), 72);
Font = CreateFont(Fntheight, 0, 0, 0, 400, 0, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv");
SelectObject(dc, Font);
TEXTMETRIC tm;
GetTextMetrics(dc, &tm);
ReleaseDC(NULL, dc);
dyStatbar = tm.tmHeight + tm.tmExternalLeading + (7*dyBorder);
CharWidth = tm.tmMaxCharWidth;
Pos=0;
TextBox=AddBox("",w);
NumLock = NumBox ? AddBox("",3) : NULL;
CapsLock = CapsBox ? AddBox("",3) :NULL;
nMenu=0;
OldText=NULL;
}
StatusBar::~StatusBar()
{
if (OldText) delete[] OldText;
DeleteObject(Font);
}
BOOL StatusBar::SetupWindow()
{
nMenu=0;
ParsePopup(GetMenu(ParentHWnd));
return TRUE;
}
void StatusBar::SetText(char *T)
{
TextBox->SetText(T);
DrawText(TextBox);
}
void StatusBar::SetText(int Box,char *T)
{
StatusBox *S=BoxList[Box];
S->SetText(T);
DrawText(S);
}
void StatusBar::DrawText(StatusBox *S)
{
if (!S->Text) return;
RECT rc,rcTemp;
HDC dc = GetDC(ParentHWnd);
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
rcTemp.top = rc.top + dyBorder*4;
rcTemp.bottom = rc.bottom - dyBorderx3;
rcTemp.left = dyBorder + S->x;
rcTemp.right = rcTemp.left + S->w- dyBorder;
SelectObject(dc, Font);
SetTextColor(dc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, GetSysColor(COLOR_BTNFACE));
ExtTextOut(dc, rcTemp.left + dyBorderx2, rcTemp.top,
ETO_OPAQUE | ETO_CLIPPED, &rcTemp, S->Text,
strlen(S->Text), NULL);
ReleaseDC(ParentHWnd, dc);
}
void StatusBar::Paint(HDC dc)
{
RECT rc,rcTemp;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
/* Border color */
HBRUSH Brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
rcTemp = rc;
rcTemp.top += dyBorderx2;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* Shadow color */
Brush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
/* Top and left of boxes */
StatusBox *Ptr=BoxList.GetFirst();
while (Ptr)
{
rcTemp.top = rc.top + dyBorderx3;
rcTemp.bottom = rcTemp.top + dyBorder;
rcTemp.left = Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w;
FillRect(dc, &rcTemp, Brush);
rcTemp.bottom = rc.bottom - dyBorderx2;
rcTemp.right = rcTemp.left + dyBorder;
FillRect(dc, &rcTemp, Brush);
BoxList.GetNext(Ptr);
}
DeleteObject(Brush);
Brush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
/* Bottom and right of boxes */
Ptr=BoxList.GetFirst();
while (Ptr)
{
rcTemp.top = rc.bottom - dyBorderx3;
rcTemp.bottom = rcTemp.top + dyBorder;
rcTemp.left = Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w;
FillRect(dc, &rcTemp, Brush);
rcTemp.top = rc.top + dyBorderx3;
rcTemp.left = Ptr->x+Ptr->w;
rcTemp.right = rcTemp.left + dyBorder;
FillRect(dc, &rcTemp, Brush);
BoxList.GetNext(Ptr);
}
/* Across the top */
rcTemp = rc;
rcTemp.top += dyBorder;
rcTemp.bottom = rcTemp.top + dyBorder;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* solid black line across top */
Brush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
rcTemp = rc;
rcTemp.bottom = rcTemp.top;
rcTemp.bottom += dyBorder;
FillRect(dc, &rcTemp, Brush);
DeleteObject(Brush);
/* now the text, with the button face background */
SelectObject(dc, Font);
SetTextColor(dc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, GetSysColor(COLOR_BTNFACE));
/* Text */
Ptr=BoxList.GetFirst();
while (Ptr)
{
if (Ptr->Text)
{
rcTemp.top = rc.top + dyBorder*4;
rcTemp.bottom = rc.bottom - dyBorderx3;
rcTemp.left = dyBorder + Ptr->x;
rcTemp.right = rcTemp.left + Ptr->w - dyBorder;
ExtTextOut(dc, rcTemp.left + dyBorderx2, rcTemp.top,
ETO_OPAQUE | ETO_CLIPPED, &rcTemp, Ptr->Text,
strlen(Ptr->Text), NULL);
}
BoxList.GetNext(Ptr);
}
}
BOOL StatusBar::bInKeyDown=FALSE;
BOOL StatusBar::WMKeyUp(TMSG &)
{
bInKeyDown = FALSE;
return TRUE;
}
BOOL StatusBar::WMKeyDown(TMSG &Msg)
{
if ( !bInKeyDown )
{
if ( Msg.wParam == VK_CAPITAL ) SetCapsLockText();
else if ( Msg.wParam == VK_NUMLOCK ) SetNumLockText();
bInKeyDown = TRUE;
}
return TRUE;
}
BOOL StatusBar::WMFocus(TMSG &)
{
SetCapsLockText();
SetNumLockText();
return TRUE;
}
void StatusBar::SetNumLockText()
{
/* Num Lock Text */
if (NumLock)
{
int State=GetKeyState(VK_NUMLOCK) & 0x0001;
NumLock->SetText(State ? "NUM" : "");
DrawText(NumLock);
}
}
void StatusBar::SetCapsLockText()
{
/* Caps Lock Text */
if (CapsLock)
{
int State=GetKeyState(VK_CAPITAL) & 0x0001;
CapsLock->SetText(State ? "CAPS" : "");
DrawText(CapsLock);
}
}
void StatusBar::Invalidate()
{
RECT rc;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
InvalidateRect(ParentHWnd,&rc,TRUE);
}
BOOL StatusBar::WMSize(TMSG &)
{
RECT rc;
GetClientRect(ParentHWnd, &rc);
rc.top = rc.bottom - dyStatbar;
if (rc.top < StatRecSizeAdv.top)
{
/* Window SHRANK, need to invalidate current status rect */
InvalidateRect(ParentHWnd, &rc,FALSE);
}
else
{
/* Window GREW, need to invalidate prev status rect */
InvalidateRect(ParentHWnd, &StatRecSizeAdv,TRUE);
}
return TRUE;
}
BOOL StatusBar::WMGetMinMaxInfo(TMSG &)
{
GetClientRect(ParentHWnd, &StatRecSizeAdv);
StatRecSizeAdv.top = StatRecSizeAdv.bottom - dyStatbar;
return TRUE;
}
#define NOMENU 0
// WM_MENUSELECT
BOOL StatusBar::WMMenuSelect(TMSG &Msg)
{
int nMenuID=NOMENU;
WORD flags=LLHW(Msg);
WORD item=LOWWPARAM(Msg.wParam);
if (HILP32(Msg) == NULL && flags == 0xffff)
{
// Exiting menu mode. hMenu && hmenuPopup are NULL.
//nMenuID = NOMENU;
if (OldText)
{
SetText(OldText);
delete[] OldText;
OldText=NULL;
}
return TRUE;
}
else if (flags & MF_SYSMENU)
{
// System menu is up
if (!(flags & MF_POPUP)) nMenuID = item;
// System menu item is selected
// System menu: item contains SC_* code.
else nMenuID = IDM_SYSMENU;
// System menu and no item is selected
}
else
{
if ((flags & MF_POPUP))
{
// Pulling down a popup submenu: hmenuPopup contains popup handle.
#ifdef WIN32
HMENU hm=GetSubMenu((HMENU) Msg.lParam,item);
for (int i=0;i<nMenu;i++)
if (hm==hMenu[i])
{
nMenuID=IDS_POPUP1+i;
break;
}
#else
for (int i=0;i<nMenu;i++)
if (item==hMenu[i])
{
nMenuID=IDS_POPUP1+i;
break;
}
#endif
}
else nMenuID = item;
}
//SetStatbarText(hwnd, nMenuID,TRUE);
char temp[255];
if ( LoadString(App::hInstance, nMenuID, temp, 255) == 0)
strcpy(temp,"");
if (!OldText) OldText=strdup(TextBox->Text ? TextBox->Text : ""); // null is reserved to indicate not in menu
SetText(temp);
return TRUE;
}
void StatusBar::ParsePopup(HMENU hm)
{
if (hm==NULL) return;
HMENU hm2;
int n=GetMenuItemCount(hm);
for (int i=0;i<n;i++)
{
hm2=GetSubMenu(hm,i);
if (hm2)
{
// add hm2 to hmenu list
hMenu[nMenu++]=hm2;
ParsePopup(hm2);
}
}
}