#ifdef _WIN32
# ifdef __BORLANDC__
# pragma option -a4 // Word-Ausrichtung bei ACCEL
# else
# pragma pack(4) // Visual C
# endif
#else
# ifdef __BORLANDC__
# pragma option -a- // Byte-Ausrichtung bei ACCEL
# endif
#endif
#include <windows.h>
#include <windowsx.h> // Message-Cracker
#ifndef GET_WM_COMMAND_CMD
# define GET_WM_COMMAND_CMD(wp,lp) HIWORD(lp) //fehlt bei BC31 windowsx.h
#endif
#include "toolstat.h"
#include <commctrl.h> // in dieser Reihenfolge!
#ifndef _WIN32
# undef TB_BUTTONCOUNT // falsch definiert in commctrl.h: WM_USER+25
# define TB_BUTTONCOUNT (WM_USER+24)
# undef TB_COMMANDTOINDEX // falsch definiert in commctrl.h: WM_USER+26
# define TB_COMMANDTOINDEX (WM_USER+25)
# undef TB_SAVERESTORE // falsch definiert in commctrl.h: WM_USER+28
# define TB_SAVERESTORE (WM_USER+26)
# undef TB_CUSTOMIZE // falsch definiert in commctrl.h: WM_USER+29
# define TB_CUSTOMIZE (WM_USER+27)
#endif
HINSTANCE gHInstance; /* globales HInstance */
LPCTSTR StdProfile; /* INI-Datei */
LPCTSTR HelpFileName; /* Hilfe-Datei (für Kontexthilfe bei Werkzeugleiste)*/
HINSTANCE hCommCtrl; /* Handle der dynamisch geladenen DLL*/
HWND MainWnd; /* Handle des Hauptfensters*/
HMENU MainMenu; /* Handle des Hauptmenüs, wird zu oft gebraucht */
HACCEL AccTable; /* für Anzeige in ToolTips */
HWND Toolbar; /* Handle für Windows-Werkzeugleiste */
HWND Status; /* Handle für Windows-Statuszeile */
HLOCAL ButtonDescript; /* Kurzbeschreibungen zur Konfiguration der
Werkzeugleiste */
HGLOBAL ButtonInfo; /* Ressourcen-Objekt mit nachfolgenden Daten */
HLOCAL MenuBitmaps; /* Bitmap-Symbole für Menü */
#ifndef _WIN32
typedef VOID (WINAPI*tInitCommonControls)(VOID);
typedef HWND (WINAPI*tCreateStatusWindow)(LONG dwStyle, LPCTSTR lpszText,
HWND hwndParent, UINT wID);
typedef HWND (WINAPI*tCreateToolbar)(HWND hParent, LONG dwStyle, UINT wID,
int nBitmaps, HINSTANCE hBMInst, UINT wBMID, LPTBBUTTON lpButtons,
int iNumButtons);
#endif
void LoadButtonInfo(void) {
ButtonInfo=FindResource(gHInstance,MAKEINTRESOURCE(98),RT_RCDATA);
if (ButtonInfo) ButtonInfo=LoadResource(gHInstance,ButtonInfo);
}
void SetMenuBitmaps(void) {
LPRC_ButtonInfo rp;
int j,k;
HBITMAP bar,obar,bm,obm,near*mbp;
HDC dc,dc_bar,dc_bm;
DWORD p;
if (!Toolbar) { // tja!!
LoadButtonInfo();
if (!ButtonInfo) return;
}
rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);
p=GetMenuCheckMarkDimensions();
dc=GetDC(MainWnd);
dc_bar=CreateCompatibleDC(dc);
dc_bm=CreateCompatibleDC(dc);
bar=LoadBitmap(gHInstance,MAKEINTRESOURCE(98));
obar=SelectObject(dc_bar,bar);
MenuBitmaps=LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT,256*sizeof(HBITMAP));
mbp=LocalLock(MenuBitmaps); j=0;
for (k=0;rp->id;rp++,k+=16) {
if (STY(rp->stasty)&TBSTYLE_CHECK) continue; // CHECKbar: ohne Bitmap!
bm=CreateCompatibleBitmap(dc,LOWORD(p),HIWORD(p));
obm=SelectObject(dc_bm,bm);
StretchBlt(dc_bm,0,0,LOWORD(p),HIWORD(p),dc_bar,k,0,16,15,SRCCOPY);
// BitBlt(dc_bm,0,0,LOWORD(p),HIWORD(p),dc_bar,k+(16-LOWORD(p))/2,(15-HIWORD(p))/2,SRCCOPY);
SelectObject(dc_bm,obm); // Bitmap herauslösen
SetMenuItemBitmaps(MainMenu,rp->id,0,bm,bm);
*mbp++=bm; j++;
}
LocalUnlock(MenuBitmaps);
LocalReAlloc(MenuBitmaps,j*sizeof(HBITMAP),0);
ReleaseDC(MainWnd,dc);
DeleteDC(dc_bm);
SelectObject(dc_bar,obar);
DeleteObject(bar);
DeleteDC(dc_bar);
UnlockResource(ButtonInfo);
if (!Toolbar) FreeResource(ButtonInfo);
}
void DeleteMenuBitmaps(void) {
int k=LocalSize(MenuBitmaps)/sizeof(HBITMAP);
HBITMAP near*mbp=LocalLock(MenuBitmaps);
for (;k;k--) {
if (*mbp) DeleteObject(*mbp);
mbp++;
}
LocalUnlock(MenuBitmaps);
MenuBitmaps=LocalFree(MenuBitmaps);
}
static void MakeButtons(void) {
/*Erzeugt neue Werkzeugleiste oder setzt die vorher geleerte auf Startvorgaben*/
PTBBUTTON b,bb;
int i,k;
LPRC_ButtonInfo rp;
rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);
/*Durchzählen der notwendigen TBButtons*/
for (k=0;rp->id;rp++) {
if (STY(rp->stasty)&TBSTYLE_SEP) k++;
if (!(STA(rp->stasty)&TBSTATE_HIDDEN)) k++;
}
UnlockResource(ButtonInfo);
i=k*sizeof(TBBUTTON);
/*Anlegen des TBButton-Arrays (eigentlich sinnlos, wenn's was zu laden gibt)*/
b=(PTBBUTTON)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,i);
rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);
for (bb=b,i=0;rp->id;rp++,i++) {
if (STY(rp->stasty)&TBSTYLE_SEP) {
bb->fsStyle=TBSTYLE_SEP; /*heißt hier: Leerraum davor!*/
bb++;
}
if (!(STA(rp->stasty)&TBSTATE_HIDDEN)) {
bb->iBitmap=i;
bb->idCommand=rp->id;
*(WORD*)(&bb->fsState)=(WORD)(rp->stasty&~0xF108);
bb->iString=i;
bb++;
}
}
UnlockResource(ButtonInfo);
/*i entspricht jetzt der Anzahl der Bilder! Erzeugen der Toolbar*/
if (Toolbar) SendMessage(Toolbar,TB_ADDBUTTONS,k,(LPARAM)(LPTBBUTTON)b);
else Toolbar=
#ifdef _WIN32
CreateToolbarEx
#else
((tCreateToolbar)GetProcAddress(hCommCtrl,MAKEINTRESOURCE(7)))
#endif
(MainWnd,WS_CHILD|WS_VISIBLE|WS_BORDER|
CCS_ADJUSTABLE|TBSTYLE_TOOLTIPS|TBSTYLE_WRAPABLE,
98,i,gHInstance,98,(LPTBBUTTON)b,k
#ifdef _WIN32
,16,15,16,15,sizeof(TBBUTTON)
#endif
);
LocalFree((HANDLE)b);
}
LPCTSTR GetFileNamePtr(LPCTSTR s) {
LPCTSTR r;
TCHAR c;
for (r=s;;) {
c=*s; s=AnsiNext(s);
switch (c) {
case ':':
case '\\':
case '/': r=s; break;
case 0: return r;
}
}
}
LPCTSTR lstrchr(LPCTSTR s, TCHAR c) {
/* MBCS-sichere Zeichen- oder LeadByte-Suche */
for(;;) {
if (*s==c) return s;
if (!*s) return NULL;
s=AnsiNext(s);
}
}
WORD Swap(WORD w) {
return (w>>8)|(w<<8);
}
static void SaveRestore(BOOL save) {
/*Win9x speichert unter:
HKCU\Software\Microsoft\Windows\CurrentVersion\ToolbarState\<section>*/
#ifdef _WIN32
TBSAVEPARAMS sp;
TCHAR s[MAX_PATH];
GetModuleFileName(gHInstance,s,elemof(s));
sp.hkr=HKEY_CURRENT_USER;
sp.pszSubKey=T("Software\\Microsoft\\Windows\\CurrentVersion\\ToolbarState");
sp.pszValueName=GetFileNamePtr(s);
SendMessage(Toolbar,TB_SAVERESTORE,(WPARAM)save,(LPARAM)&sp);
#else
LPCTSTR vsrec[2];
TCHAR s[MAX_PATH];
GetModuleFileName(gHInstance,s,elemof(s));
vsrec[0]=GetFileNamePtr(s);
vsrec[1]=StdProfile;
if (StdProfile && Swap(LOWORD(GetVersion()))<3*256+95) {
/*falls in einer privaten .INI, dann einen besseren Sektionsnamen geben*/
GetClassName(Toolbar,s,sizeof(s)); /*sollte "ToolbarWindow" liefern*/
vsrec[0]=s;
}
SendMessage(Toolbar,TB_SAVERESTORE,(WPARAM)save,(LPARAM)(LPSTR)vsrec);
#endif
}
void ToggleToolbar(UINT MenuID) {
int i;
RECT R;
// CalcClientRect(&R); // vorher
if (!Toolbar) {
if ((UINT)hCommCtrl>32) {
ButtonDescript=LocalAlloc(LMEM_FIXED,512);
i=LoadString(gHInstance,98,(NPSTR)ButtonDescript,256)+1;
i+=LoadString(gHInstance,99,(NPSTR)ButtonDescript+i,256)+1;
ButtonDescript=LocalReAlloc(ButtonDescript,i,LMEM_MOVEABLE);
LoadButtonInfo();
if (ButtonInfo) MakeButtons();
}
if (Toolbar) SaveRestore(FALSE); /*Konfiguration laden*/
else if (MenuID) /*Noch Null: Da ging etwas schief!*/
EnableMenuItem(MainMenu,MenuID,MF_GRAYED);
}else{
DestroyWindow(Toolbar);
FreeResource(ButtonInfo);
LocalFree(ButtonDescript);
Toolbar=0;
}
if (MenuID) CheckMenuItem(MainMenu,MenuID,
Toolbar?MF_CHECKED:MF_UNCHECKED);
// i=R.top;
CalcClientRect(&R);
// if (!(GetClassLong(MainWnd,GCL_STYLE)&CS_VREDRAW)) {
// UpdateWindow(MainWnd);
// ScrollWindow(MainWnd,0,R.top-i,&R,NULL);
// }
InvalidateRect(MainWnd,&R,TRUE);
}
void ToggleStatus(UINT MenuID) {
RECT R;
if (!Status) {
if ((UINT)hCommCtrl>32)
Status=
#ifdef _WIN32
CreateStatusWindow
#else
((tCreateStatusWindow)GetProcAddress(hCommCtrl,MAKEINTRESOURCE(6)))
#endif
(WS_VISIBLE|WS_CHILD|WS_BORDER,NULL,MainWnd,99);
if (!Status && MenuID) /*Misserfolg*/
EnableMenuItem(MainMenu,MenuID,MF_GRAYED);
}else{
DestroyWindow(Status);
Status=0;
}
if (MenuID)
CheckMenuItem(MainMenu,MenuID,Status?MF_CHECKED:MF_UNCHECKED);
#ifdef _WIN32
if (GetClassLong(MainWnd,GCL_STYLE)&CS_VREDRAW) {
#else
if (GetClassWord(MainWnd,GCW_STYLE)&CS_VREDRAW) {
#endif
CalcClientRect(&R);
InvalidateRect(MainWnd,&R,TRUE);
}
}
void WMMenuSelect(UINT id, UINT flags) {
TCHAR s[128];
if (!Status) return;
if (flags==0xFFFF) {
SendMessage(Status,SB_SIMPLE,FALSE,0);
return;
}
if (flags&MF_POPUP) {
int sub=0; /* Ebenen-Zähler */
HMENU submenu;
for(;;){
sub++; /* Eine Ebene tiefer */
submenu=(HMENU)id; /* ist ein Popup-Menü-Handle */
id=(UINT)GetSubMenu(submenu,0); /* Vielleicht noch ein Popup-Menü? */
if (!id) { /* nein, dann raus! */
id=GetMenuItemID(submenu,0)-sub; /* endgültige ID */
break;
}
}
}
if (!LoadString(gHInstance,id,s,sizeof(s))
&& flags&MF_SYSMENU) {
id&=0x8FF0;
if (flags&MF_POPUP) id=0x8FF0;
LoadString(hCommCtrl,id&0x8FF0,s,sizeof(s)); /*da sind sie!*/
}
SendMessage(Status,SB_SIMPLE,TRUE,0);
SendMessage(Status,SB_SETTEXT,255|SBT_NOBORDERS,(LPARAM)(LPSTR)s);
}
#ifndef _WIN32
static LPRC_ButtonInfo FindButton(UINT iButton) {
/*sperrt ButtonInfo und setzt Zeiger auf Knopf mit gleicher ID*/
LPRC_ButtonInfo rp;
TBBUTTON b;
SendMessage(Toolbar,TB_GETBUTTON,iButton,(LPARAM)(LPTBBUTTON)&b);
for (rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);rp->id;rp++) {
if (rp->id==b.idCommand) break;
}
return rp;
}
#endif
void Accel2Text(LPACCEL accel, LPTSTR s) {
int i;
for (i=0; i<3; i++) {
if (accel->fVirt&(FSHIFT<<i)) {
TCHAR s2[16];
GetKeyNameText(MAKELONG(0,MapVirtualKey(VK_SHIFT+i,0)),
s2,elemof(s2));
s+=wsprintf(s,T("%s+"),(LPTSTR)s2);
}
}
if (accel->fVirt&FVIRTKEY) {
GetKeyNameText(MAKELONG(0,MapVirtualKey(accel->key,0)),
s,32);
}else{
WORD k=accel->key;
if (k<32) {
*s++='^'; k+=64; /*zur Kenntlichmachung WM_CHAR*/
}
*s++=(TCHAR)k;
*s=0;
}
}
#ifdef _WIN32
// unter Win32 kommt man nicht so einfach an die Tabelle heran!
static HLOCAL AccMem;
LPACCEL LockAccel(HACCEL a) {
int i=CopyAcceleratorTable(a,NULL,0);
AccMem=LocalAlloc(LMEM_FIXED,i*sizeof(ACCEL)+1);
CopyAcceleratorTable(a,AccMem,i);
((LPBYTE)AccMem)[i*sizeof(ACCEL)]=0x80; // Terminator
return AccMem;
}
# define UnlockAccel(a) LocalFree(AccMem)
#else
# define LockAccel(a) (LPACCEL)LockResource(a)
# define UnlockAccel(a) UnlockResource(a)
#endif
void AppendAccel(LPTSTR s, UINT id) {
LPACCEL acc;
TCHAR s2[32];
for (acc=LockAccel(AccTable);!(acc->fVirt&0x80);acc++) {
if ((UINT)acc->cmd==id) {
Accel2Text(acc,s2);
wsprintf(s+lstrlen(s),T(" (%s)"),(LPTSTR)s2);
break; /*nicht mehrere! (unübersichtlich)*/
}
}
UnlockAccel(AccTable);
}
void SetMenuAccels(HMENU m, HACCEL a, TCHAR delim) {
LPACCEL acc;
UINT ms;
int cc;
TCHAR s[64];
TCHAR s2[32];
for (acc=LockAccel(a);!(acc->fVirt&0x80);acc++) {
ms=GetMenuState(m,acc->cmd,0);
if (!(ms&(MF_BITMAP|MF_OWNERDRAW))) {
cc=GetMenuString(m,acc->cmd,s,elemof(s),MF_BYCOMMAND);
if (!lstrchr(s,delim)) { /*nicht mehrfach*/
Accel2Text(acc,s2);
wsprintf(s+cc,T("%c%s"),delim,(LPTSTR)s2);
ModifyMenu(m,acc->cmd,ms,acc->cmd,s);
}
}
}
UnlockAccel(a);
}
#ifndef _WIN32
static HANDLE hAdjust; /*temporär für das Einrichten der Toolbar*/
#endif
LRESULT HandleToolStat(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
// lPar: LongRec absolute lParam;
// ttt: PToolTipText absolute lParam;
LPRC_ButtonInfo rp;
LPSTR sp;
switch (Msg) {
case WM_NCCREATE: {
#ifdef _WIN32 // bei Win32 nur für Systemmenü-Strings
hCommCtrl=LoadLibrary("comctl32.dll");
InitCommonControls();
#else // bei Win16 darf die DLL auch fehlen
UINT osem=SetErrorMode(SEM_NOOPENFILEERRORBOX);
hCommCtrl=LoadLibrary("COMMCTRL.DLL");
SetErrorMode(osem);
if ((UINT)hCommCtrl>32)
((tInitCommonControls)GetProcAddress(hCommCtrl,MAKEINTRESOURCE(17)))();
#endif
}break;
case WM_CREATE: {
MainWnd=Wnd;
MainMenu=((LPCREATESTRUCT)lParam)->hMenu;
if (MainMenu) SetMenuAccels(MainMenu,AccTable,9);
}break;
case WM_SIZE: {
if (Toolbar) SendMessage(Toolbar,Msg,0,0);
if (Status) SendMessage(Status,Msg,0,0);
}break;
#ifndef _WIN32
case WM_COMMAND: switch (LOWORD(wParam)) {
case 98: switch (GET_WM_COMMAND_CMD(wParam,lParam)) {
case TBN_BEGINDRAG: SendMessage(Wnd,WM_MENUSELECT,(WPARAM)lParam,0); break;
case TBN_ENDDRAG: SendMessage(Wnd,WM_MENUSELECT,0,0x0000FFFF); break;
case TBN_BEGINADJUST: {
int i,j;
/*Länge der längsten Beschreibung bestimmen*/
rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);
sp=LocalLock(ButtonDescript);
i=0;
for (i=0;rp->id;rp++) {
j=lstrlen(sp);
i=max(i,j);
sp+=j+1;
}
LocalUnlock(ButtonDescript);
UnlockResource(ButtonInfo);
/*Speicherblock anfordern und für TBN_AdjustInfo bereithalten*/
hAdjust=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
sizeof(ADJUSTINFO)+i);
}break;
case TBN_ADJUSTINFO: {
/*Solange AdjustInfos liefern, bis lPar.lo zu groß wird*/
rp=(LPRC_ButtonInfo)LockResource(ButtonInfo);
rp+=LOWORD(lParam); /*lPar.lo = Button-Index*/
if (rp->id) {
LPADJUSTINFO ai=(LPADJUSTINFO)GlobalLock(hAdjust);
ai->tbButton.iBitmap=LOWORD(lParam);
ai->tbButton.idCommand=rp->id;
*(LPWORD)&ai->tbButton.fsState=rp->stasty&~0xF108;
ai->tbButton.idsHelp=LOWORD(lParam);
sp=LocalLock(ButtonDescript);
for (;LOWORD(lParam);LOWORD(lParam)--) { /*richtigen String suchen*/
sp+=lstrlen(sp)+1;
}
lstrcpy(ai->szDescription,sp);
LocalUnlock(ButtonDescript);
GlobalUnlock(hAdjust);
return (LRESULT)hAdjust;
}
UnlockResource(ButtonInfo);
}break;
case TBN_ENDADJUST: GlobalFree(hAdjust); break;
case TBN_RESET: {
while (SendMessage(Toolbar,TB_DELETEBUTTON,0,0)); /*alle löschen*/
MakeButtons(); /*und neu setzen*/
SaveRestore(TRUE); /*und speichern*/
}break;
case TBN_QUERYINSERT: return TRUE; /*stets links einfügen lassen*/
case TBN_QUERYDELETE: {
rp=FindButton(LOWORD(lParam));
if (!(STY(rp->stasty)&0x10)) {
UnlockResource(ButtonInfo);
return TRUE; /*Aktion erlauben*/
}
UnlockResource(ButtonInfo);
}break;
case TBN_TOOLBARCHANGE: SaveRestore(TRUE); break; /*abspeichern*/
case TBN_CUSTHELP: WinHelp(MainWnd,HelpFileName,HELP_CONTEXT,98);
}
}break;
#endif
case WM_NOTIFY: { /*ab Win95*/
#define ttt ((LPTOOLTIPTEXT)lParam)
#ifndef _WIN32
if (IsBadWritePtr(ttt,sizeof(TOOLTIPTEXT))) break;
#endif
switch (ttt->hdr.code) {
case TTN_NEEDTEXT: {
/*wParam = Button-Nummer ermitteln*/
for (rp=LockResource(ButtonInfo),wParam=0;rp->id;rp++,wParam++) {
if ((UINT)rp->id==ttt->hdr.idFrom) break;
}
UnlockResource(ButtonInfo);
sp=LocalLock(ButtonDescript);
while (wParam) { /*richtigen String suchen*/
sp+=lstrlen(sp)+1;
wParam--;
}
lstrcpyn(ttt->szText,sp,sizeof(ttt->szText));
LocalUnlock(ButtonDescript);
AppendAccel(ttt->szText,ttt->hdr.idFrom);
}break;
#ifdef _WIN32
case TBN_QUERYINSERT:
case TBN_QUERYDELETE: {
}return TRUE;
case TBN_BEGINDRAG: WMMenuSelect(
((LPTBNOTIFY)lParam)->iItem,0); break;
case TBN_ENDDRAG: WMMenuSelect(0,0xFFFF); break;
case TBN_CUSTHELP: WinHelp(MainWnd,HelpFileName,HELP_CONTEXT,98); break;
#endif
}
#undef ttt
}break;
case WM_MENUSELECT: WMMenuSelect(
#ifdef _WIN32 /* Fallstrick Win32 */
HIWORD(wParam)&MF_POPUP
?(UINT)GetSubMenu((HMENU)lParam,LOWORD(wParam))
:LOWORD(wParam),
HIWORD(wParam)
#else
wParam,LOWORD(lParam)
#endif
); break;
case WM_DESTROY: { /*Fenster ggf. aufräumen*/
if (Toolbar) ToggleToolbar(0); /*Menü-ID sowieso unwichtig*/
if (Status ) ToggleStatus(0);
}break;
case WM_NCDESTROY: {
if ((UINT)hCommCtrl>32) FreeLibrary(hCommCtrl);
}break;
}
return 0;
}
void CalcClientRect(LPRECT R) {
RECT R2;
GetClientRect(MainWnd,R);
if (Toolbar) {
GetWindowRect(Toolbar,&R2);
ScreenToClient(MainWnd,(LPPOINT)&R2.right);
R->top=R2.bottom;
}
if (Status) {
GetWindowRect(Status,&R2);
ScreenToClient(MainWnd,(LPPOINT)&R2.left);
R->bottom=R2.top;
}
}
Detected encoding: ANSI (CP1252) | 4
|
|