2326 lines
60 KiB
C++
2326 lines
60 KiB
C++
/*-----------------------------------------------------------------------
|
|
|
|
|
| CTL3D
|
|
|
|
|
| Copyright Microsoft Corporation 1992. All Rights Reserved.
|
|
|
|
|
|
|
|
| This module contains the functions to give windows controls a 3d effect
|
|
|
|
|
| This source is made public for your edification and debugging pleasure
|
|
|
|
|
| PLEASE do not make any changes or release static versions of this DLL
|
|
| send e-mail to me (wesc) if you have feature requests or bug fixes.
|
|
|
|
|
| Thanks -- Wes.
|
|
|
|
|
|
|
|
| History:
|
|
| 1-Jan-92 : Added OOM handling on GetDC (not really necessary but
|
|
| XL4 OOM failure testing made GetDC return NULL)
|
|
|
|
|
| 1-Jan-92 : Check wasn't getting redrawn when state changed in
|
|
| the default button proc.
|
|
|
|
|
| 29-Jan-92: If button has the focus and app is switched in, we weren't
|
|
| redrawing the entire button check & text. Force redraw
|
|
| of these on WM_SETFOCUS message.
|
|
|
|
|
| 3-Feb-92: Fixed switch in via task manager by erasing the buttons
|
|
| backgound on WM_SETFOCUS (detect this when wParam == NULL)
|
|
|
|
|
| 4-Apr-92: Make it work with OWNERDRAW buttons
|
|
|
|
|
| 22-Apr-92: Removed Excel specific code
|
|
|
|
|
| 19-May-92: Turn it into a DLL
|
|
|
|
|
| May-Jun92: Lots o' fixes & enhancements
|
|
|
|
|
| 23-Jun-92: Added support for hiding, sizing & moving
|
|
|
|
|
| 24-Jun-92: Make checks & radio button circles draw w/ window
|
|
| text color 'cause they are drawn on window bkgnd
|
|
|
|
|
| 30-Jun-92: (0.984) Fix bug where EnableWindow of StaticText doesn't
|
|
| redraw properly. Also disable ctl3d when verWindows > 3.1
|
|
|
|
|
| 1-Jul-92: Added WIN32 support (davegi) (not in this source)
|
|
|
|
|
| 2-Jul-92: (0.984) Disable when verWindows >= 4.0
|
|
|
|
|
| 20-Jul-92: (0.985) Draw focus rects of checks/radios properly on non
|
|
| default sized controls.
|
|
|
|
|
| 21-Jul-92: (0.990) Ctl3dAutoSubclass
|
|
|
|
|
| 21-Jul-92: (0.991) ported DaveGi's WIN32 support
|
|
|
|
|
| 22-Jul-92: (0.991) fixed Ctl3dCtlColor returning FALSE bug
|
|
|
|
|
| 4-Aug-92: (0.992) Graphic designers bug fixes...Now subclass
|
|
| regular buttons + disabled states for checks & radios
|
|
|
|
|
| 6-Aug-92: (0.993) Fix bug where activate via taskman & group
|
|
| box has focus, & not centering text in buttons
|
|
|
|
|
| 6-Aug-92: (0.993) Tweek drawing next to scroll bars.
|
|
|
|
|
| 13-Aug-92: (0.994) Fix button focus rect bug drawing due to
|
|
| Win 3.0 DrawText bug.
|
|
|
|
|
| 14-Aug-92: (1.0) Release of version 1.0
|
|
| Don't draw default button border on BS_DEFPUSHBUTTON
|
|
| pushbuttons
|
|
| Fix bogus bug where Windows hangs when in a AUTORADIOBUTTON
|
|
| hold down space bar and hit arrow key.
|
|
|
|
|
| 23-Sep-92: (1.01) Made Ctl3dCtlColor call DefWindowProc so it works when
|
|
| called in a windproc.
|
|
|
|
|
| 28-Sep-92: (1.02) Added MyGetTextExtent so '&''s not considered in
|
|
| text extents.
|
|
|
|
|
| 08-Dec-92: (1.03) minor tweeks to the button text centering code
|
|
| for Publisher
|
|
|
|
|
| 11-Dec-92: (1.04) added 3d frames to dialogs
|
|
|
|
|
| 15-Dec-92: (1.05) fixed bug where group boxes redraw wrong when
|
|
| Window text is changed to something shorter
|
|
|
|
|
| ??-Dec-92: (1.06) added 3d borders
|
|
|
|
|
| 21-Dec-92: (1.07) added WM_DLGBORDER to disable borders
|
|
|
|
|
| 4-Jan-93: (1.08) fixed WM_SETTEXT bug w/ DLG frames & checks/checkboxes
|
|
| Also, WM_DLGSUBCLASS
|
|
|
|
|
| 22-Feb-93: (1.12) disabled it under Chicago
|
|
|
|
|
| 25-Feb-93: (1.13) re-add fix which allows dialog procs to
|
|
| handle WM_CTLCOLOR messages
|
|
|
|
|
| 26-April-93 (2.0) Changed to allow for second subclass. Now uses class instead of
|
|
| wndproc for subclass determination.
|
|
| store next wndproc in properties with global atoms
|
|
|
|
|
| 06-Jun-93 (2.0) Make a static linked library version.
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
#include "stdafx.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
#include "..\common\ctl3d.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define RemoveGdiObject(p) RemoveObject((HGDIOBJ *) p)
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|CTL3D Types
|
|
-----------------------------------------------------------------------*/
|
|
#ifdef WIN32
|
|
|
|
#define Win32Only(e) e
|
|
#define Win16Only(e)
|
|
#define Win32Or16(e32, e16) e32
|
|
#define Win16Or32(e16, e32) e32
|
|
|
|
#define FValidLibHandle(hlib) ((hlib) != NULL)
|
|
|
|
//
|
|
// No concept of far in Win32.
|
|
//
|
|
|
|
//
|
|
// Control IDs are LONG in Win32.
|
|
//
|
|
|
|
typedef LONG CTLID;
|
|
#define GetControlId(hwnd) GetWindowLong(hwnd, GWL_ID)
|
|
|
|
//
|
|
// Send a color button message.
|
|
//
|
|
|
|
#define SEND_COLOR_BUTTON_MESSAGE( hwndParent, hwnd, hdc ) \
|
|
((HBRUSH) SendMessage(hwndParent, WM_CTLCOLORBTN, (WPARAM) hdc, (LPARAM) hwnd))
|
|
|
|
//
|
|
// Send a color static message.
|
|
//
|
|
|
|
#define SEND_COLOR_STATIC_MESSAGE( hwndParent, hwnd, hdc ) \
|
|
((HBRUSH) SendMessage(hwndParent, WM_CTLCOLORSTATIC, (WPARAM) hdc, (LPARAM) hwnd))
|
|
|
|
#else
|
|
|
|
#ifndef TEXT
|
|
#define TEXT(a) a
|
|
#define TCHAR char
|
|
#endif
|
|
|
|
#ifndef LPTSTR
|
|
#define LPTSTR LPSTR
|
|
#endif
|
|
#define LPCTSTR LPCSTR
|
|
|
|
#define Win32Only(e)
|
|
#define Win16Only(e) e
|
|
#define Win32Or16(e32, e16) e16
|
|
#define Win16Or32(e16, e32) e16
|
|
|
|
#define FValidLibHandle(hlib) (( hlib ) > 32 )
|
|
|
|
typedef UINT CTLID;
|
|
#define GetControlId(h) GetWindowWord(h, GWW_ID)
|
|
|
|
#define SEND_COLOR_BUTTON_MESSAGE( hwndParent, hwnd, hdc ) \
|
|
((HBRUSH) SendMessage(hwndParent, WM_CTLCOLOR, (UINT) hdc, MAKELONG(hwnd, CTLCOLOR_BTN)))
|
|
|
|
#define SEND_COLOR_STATIC_MESSAGE( hwndParent, hwnd, hdc ) \
|
|
((HBRUSH) SendMessage(hwndParent, WM_CTLCOLOR, (UINT) hdc, MAKELONG(hwnd, CTLCOLOR_STATIC)))
|
|
|
|
#endif // WIN32
|
|
|
|
#define CSCONST(type) type const
|
|
#define CodeLpszDecl(lpszVar, szLit) TCHAR *lpszVar = szLit
|
|
|
|
// isomorphic to windows RECT
|
|
typedef struct {
|
|
int xLeft;
|
|
int yTop;
|
|
int xRight;
|
|
int yBot;
|
|
} RC;
|
|
|
|
// Windows Versions (Byte order flipped from GetWindowsVersion)
|
|
#define ver30 0x0300
|
|
#define ver31 0x030a
|
|
#define ver40 0x0400
|
|
|
|
// Border widths
|
|
#define dxBorder 1
|
|
#define dyBorder 1
|
|
|
|
// Index Color Table
|
|
// WARNING: change mpicvSysColors if you change the icv order
|
|
typedef UINT ICV;
|
|
#define icvBtnHilite 0
|
|
#define icvBtnFace 1
|
|
#define icvBtnShadow 2
|
|
|
|
#define icvBrushMax 3
|
|
|
|
#define icvBtnText 3
|
|
#define icvWindow 4
|
|
#define icvWindowText 5
|
|
#define icvGrayText 6
|
|
#define icvWindowFrame 7
|
|
#define icvMax 8
|
|
|
|
typedef COLORREF CV;
|
|
|
|
// CoLoR Table
|
|
typedef struct
|
|
{
|
|
CV rgcv[icvMax];
|
|
} CLRT;
|
|
|
|
|
|
// BRush Table
|
|
typedef struct
|
|
{
|
|
HBRUSH mpicvhbr[icvBrushMax];
|
|
} BRT;
|
|
|
|
|
|
// DrawRec3d flags
|
|
#define dr3Left 0x0001
|
|
#define dr3Top 0x0002
|
|
#define dr3Right 0x0004
|
|
#define dr3Bot 0x0008
|
|
|
|
#define dr3HackBotRight 0x1000 // code size is more important than aesthetics
|
|
#define dr3All 0x000f
|
|
typedef UINT DR3;
|
|
|
|
|
|
// Control Types
|
|
// Commdlg types are necessary because commdlg.dll subclasses certain
|
|
// controls before the app can call Ctl3dSubclassDlg.
|
|
#define ctButton 0
|
|
#define ctList 1
|
|
#define ctEdit 2
|
|
#define ctCombo 3
|
|
#define ctStatic 4
|
|
#define ctComboLBox 6
|
|
#define ctMax 6
|
|
|
|
// ConTroL
|
|
typedef struct
|
|
{
|
|
FARPROC lpfn;
|
|
WNDPROC lpfnDefProc;
|
|
TCHAR szClassName[12]; //KGM
|
|
} CTL;
|
|
|
|
// Control DEFinition
|
|
typedef struct
|
|
{
|
|
TCHAR sz[20];
|
|
WNDPROC lpfnWndProc;
|
|
BOOL (* lpfnFCanSubclass)(HWND, LONG, UINT);
|
|
UINT msk;
|
|
} CDEF;
|
|
|
|
// CLIent HooK
|
|
typedef struct
|
|
{
|
|
HANDLE hinstApp;
|
|
HANDLE htask;
|
|
HHOOK hhook;
|
|
} CLIHK;
|
|
|
|
#define ICLIHMAX 4
|
|
|
|
// special styles
|
|
// #define bitFCoolButtons 0x0001
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|CTL3D Function Prototypes
|
|
-----------------------------------------------------------------------*/
|
|
static VOID End3dDialogs(VOID);
|
|
static __inline BOOL FInit3dDialogs(VOID);
|
|
static BOOL DoSubclassCtl(HWND hwnd, UINT grbit);
|
|
static BOOL InternalCtl3dColorChange(BOOL fForce);
|
|
static VOID DeleteObjects(VOID);
|
|
static int IclihkFromHinst(HANDLE hinst);
|
|
static VOID PatFill(HDC hdc, RC FAR *lprc);
|
|
|
|
//#undef EXPORT_FUNC
|
|
//#define EXPORT_FUNC __export _far _pascal
|
|
|
|
LRESULT EXPORT_FUNC Ctl3dHook(int code, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC BtnWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC EditWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC ListWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC ComboWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC StaticWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC CDListWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
LRESULT EXPORT_FUNC CDEditWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
UINT EXPORT_FUNC Ctl3dSetStyle(HANDLE hinst, LPTSTR lpszName, UINT grbit);
|
|
|
|
LRESULT EXPORT_FUNC Ctl3dDlgProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam);
|
|
|
|
BOOL FBtn(HWND, LONG, UINT);
|
|
BOOL FEdit(HWND, LONG, UINT);
|
|
BOOL FList(HWND, LONG, UINT);
|
|
BOOL FCombo(HWND, LONG, UINT);
|
|
BOOL FStatic(HWND, LONG, UINT);
|
|
|
|
static HBITMAP STDCALL LoadUIBitmap(HINSTANCE, LPCSTR, COLORREF, COLORREF, COLORREF, COLORREF, COLORREF, COLORREF);
|
|
BOOL LibMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved);
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|CTL3D Globals
|
|
-----------------------------------------------------------------------*/
|
|
|
|
typedef struct _g3d
|
|
{
|
|
BOOL f3dDialogs;
|
|
int cInited;
|
|
#ifdef WIN32
|
|
ATOM aCtl3d;
|
|
#else
|
|
ATOM aCtl3dHigh;
|
|
ATOM aCtl3dLow;
|
|
#endif
|
|
|
|
// module & windows stuff
|
|
HINSTANCE hinstLib;
|
|
HINSTANCE hmodLib;
|
|
UINT verWindows;
|
|
|
|
// drawing globals
|
|
CLRT clrt;
|
|
BRT brt;
|
|
HBITMAP hbmpCheckboxes;
|
|
|
|
// Hook cache
|
|
HANDLE htaskCache;
|
|
int iclihkCache;
|
|
int iclihkMac;
|
|
CLIHK rgclihk[ICLIHMAX];
|
|
|
|
// Control info
|
|
CTL mpctctl[ctMax];
|
|
FARPROC lpfnDefDlgWndProc;
|
|
|
|
// System Metrics
|
|
int dxFrame;
|
|
int dyFrame;
|
|
int dyCaption;
|
|
int dxSysMenu;
|
|
|
|
// Windows functions
|
|
#ifndef WIN32
|
|
#endif
|
|
} G3D;
|
|
|
|
G3D g3d;
|
|
|
|
|
|
CSCONST(CDEF) mpctcdef[ctMax] =
|
|
{
|
|
{{TEXT('B'),TEXT('u'),TEXT('t'),TEXT('t'),TEXT('o'),TEXT('n'),TEXT('\0')},
|
|
BtnWndProc3d, FBtn, CTL3D_BUTTONS},
|
|
{{TEXT('L'),TEXT('i'),TEXT('s'),TEXT('t'),TEXT('B'),TEXT('o'),TEXT('x'),TEXT('\0')},
|
|
ListWndProc3d, FList, CTL3D_LISTBOXES},
|
|
{{TEXT('E'),TEXT('d'),TEXT('i'),TEXT('t'),TEXT('\0')},
|
|
EditWndProc3d, FEdit, CTL3D_EDITS},
|
|
{{TEXT('C'),TEXT('o'),TEXT('m'),TEXT('b'),TEXT('o'),TEXT('B'),TEXT('o'),TEXT('x'),TEXT('\0')},
|
|
ComboWndProc3d, FCombo, CTL3D_COMBOS},
|
|
{{TEXT('S'),TEXT('t'),TEXT('a'),TEXT('t'),TEXT('i'),TEXT('c'),TEXT('\0')},
|
|
StaticWndProc3d,FStatic,CTL3D_STATICTEXTS|CTL3D_STATICFRAMES},
|
|
{{TEXT('C'),TEXT('o'),TEXT('m'),TEXT('b'),TEXT('o'),TEXT('L'),TEXT('B'),TEXT('o'),TEXT('x'),TEXT('\0')},
|
|
ListWndProc3d, FList, CTL3D_LISTBOXES}
|
|
};
|
|
|
|
CSCONST (UINT) mpicvSysColor[] =
|
|
{
|
|
COLOR_BTNHIGHLIGHT,
|
|
COLOR_BTNFACE,
|
|
COLOR_BTNSHADOW,
|
|
COLOR_BTNTEXT,
|
|
COLOR_WINDOW,
|
|
COLOR_WINDOWTEXT,
|
|
COLOR_GRAYTEXT,
|
|
COLOR_WINDOWFRAME
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| CTL3D Utility routines
|
|
-----------------------------------------------------------------------*/
|
|
|
|
static FARPROC LpfnGetDefWndProcNull(HWND hwnd)
|
|
{
|
|
Win32Only(return (FARPROC) GetProp(hwnd, (LPCTSTR) g3d.aCtl3d));
|
|
Win16Only(return (FARPROC) MAKELONG((UINT) GetProp(hwnd, (LPCSTR) g3d.aCtl3dLow),
|
|
GetProp(hwnd, (LPCSTR) g3d.aCtl3dHigh)));
|
|
}
|
|
|
|
static FARPROC LpfnGetDefWndProc(HWND hwnd, int ct)
|
|
{
|
|
FARPROC lpfnWndProc;
|
|
|
|
lpfnWndProc = LpfnGetDefWndProcNull(hwnd);
|
|
if (lpfnWndProc == NULL) {
|
|
if (ct == ctMax) {
|
|
lpfnWndProc = g3d.lpfnDefDlgWndProc;
|
|
}
|
|
else {
|
|
lpfnWndProc = (FARPROC) g3d.mpctctl[ct].lpfnDefProc;
|
|
}
|
|
|
|
Win32Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3d, (HANDLE) (DWORD) lpfnWndProc));
|
|
Win16Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3dLow, (HANDLE) LOWORD(lpfnWndProc)));
|
|
Win16Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3dHigh, (HANDLE) HIWORD(lpfnWndProc)));
|
|
}
|
|
return lpfnWndProc;
|
|
}
|
|
|
|
static VOID SubclassWindow(HWND hwnd, FARPROC lpfnSubclassProc)
|
|
{
|
|
FARPROC lpfnWndProc;
|
|
|
|
// Is this already subclassed by CTL3D?
|
|
if (LpfnGetDefWndProcNull(hwnd) == (FARPROC) NULL)
|
|
{
|
|
// Has a ctl3d function been added to the subclass chain
|
|
// without us knowing, this can happen with MFC.
|
|
//
|
|
SendMessage(hwnd, WM_DLGSUBCLASS, 0, 0L);
|
|
|
|
if (LpfnGetDefWndProcNull(hwnd) == (FARPROC) NULL)
|
|
{
|
|
lpfnWndProc = (FARPROC)SetWindowLong((HWND) hwnd, GWL_WNDPROC, (LONG) lpfnSubclassProc);
|
|
Win32Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3d, (HANDLE)(DWORD)lpfnWndProc));
|
|
Win16Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3dLow, (HANDLE) LOWORD(lpfnWndProc)));
|
|
Win16Only(SetProp(hwnd, (LPCTSTR) g3d.aCtl3dHigh, (HANDLE) HIWORD(lpfnWndProc)));
|
|
}
|
|
}
|
|
}
|
|
|
|
static LRESULT CleanupSubclass(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam, int ct)
|
|
{
|
|
FARPROC lpfnWinProc;
|
|
|
|
lpfnWinProc = LpfnGetDefWndProc(hwnd, ct);
|
|
Win32Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3d));
|
|
Win16Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3dLow));
|
|
Win16Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3dHigh));
|
|
return CallWindowProc((WNDPROC) lpfnWinProc, hwnd, wm, wParam, lParam);
|
|
}
|
|
|
|
|
|
static VOID DeleteObjects(VOID)
|
|
{
|
|
int icv;
|
|
|
|
for(icv = 0; icv < icvBrushMax; icv++)
|
|
RemoveGdiObject(&g3d.brt.mpicvhbr[icv]);
|
|
RemoveGdiObject(&g3d.hbmpCheckboxes);
|
|
}
|
|
|
|
static VOID PatFill(HDC hdc, RC FAR *lprc)
|
|
{
|
|
PatBlt(hdc, lprc->xLeft, lprc->yTop, lprc->xRight-lprc->xLeft, lprc->yBot-lprc->yTop, PATCOPY);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| DrawRec3d
|
|
|
|
|
|
|
|
| Arguments:
|
|
| HDC hdc:
|
|
| RC FAR *lprc:
|
|
| LONG cvUL:
|
|
| LONG cvLR:
|
|
| UINT grbit;
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
static VOID DrawRec3d(HDC hdc, RC FAR *lprc, ICV icvUL, ICV icvLR, DR3 dr3)
|
|
{
|
|
COLORREF cvSav;
|
|
RC rc;
|
|
|
|
cvSav = SetBkColor(hdc, g3d.clrt.rgcv[icvUL]);
|
|
|
|
// top
|
|
rc = *lprc;
|
|
rc.yBot = rc.yTop+1;
|
|
if (dr3 & dr3Top)
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, (LPRECT) &rc,
|
|
(LPCTSTR) NULL, 0, (int far *) NULL);
|
|
|
|
// left
|
|
rc.yBot = lprc->yBot;
|
|
rc.xRight = rc.xLeft+1;
|
|
if (dr3 & dr3Left)
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, (LPRECT) &rc,
|
|
(LPCTSTR) NULL, 0, (int far *) NULL);
|
|
|
|
if (icvUL != icvLR)
|
|
SetBkColor(hdc, g3d.clrt.rgcv[icvLR]);
|
|
|
|
// right
|
|
rc.xRight = lprc->xRight;
|
|
rc.xLeft = rc.xRight-1;
|
|
if (dr3 & dr3Right)
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, (LPRECT) &rc,
|
|
(LPCTSTR) NULL, 0, (int far *) NULL);
|
|
|
|
// bot
|
|
if (dr3 & dr3Bot)
|
|
{
|
|
rc.xLeft = lprc->xLeft;
|
|
rc.yTop = rc.yBot-1;
|
|
if (dr3 & dr3HackBotRight)
|
|
rc.xRight -=2;
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, (LPRECT) &rc,
|
|
(LPCTSTR) NULL, 0, (int far *) NULL);
|
|
}
|
|
|
|
SetBkColor(hdc, cvSav);
|
|
}
|
|
|
|
#ifdef CANTUSE
|
|
// Windows forces dialog fonts to be BOLD...URRRGH
|
|
static VOID MyDrawText(HWND hwnd, HDC hdc, LPSTR lpch, int cch, RC FAR *lprc, int dt)
|
|
{
|
|
TEXTMETRIC tm;
|
|
BOOL fChisled;
|
|
|
|
fChisled = FALSE;
|
|
if (!IsWindowEnabled(hwnd))
|
|
{
|
|
GetTextMetrics(hdc, &tm);
|
|
if (tm.tmWeight > 400)
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvGrayText]);
|
|
else
|
|
{
|
|
fChisled = TRUE;
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvBtnHilite]);
|
|
OffsetRect((LPRECT) lprc, -1, -1);
|
|
}
|
|
}
|
|
DrawText(hdc, lpch, cch, (LPRECT) lprc, dt);
|
|
if (fChisled)
|
|
{
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvBtnHilite]);
|
|
OffsetRect((LPRECT) lprc, 1, 1);
|
|
DrawText(hdc, lpch, cch, (LPRECT) lprc, dt);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
static VOID DrawInsetRect3d(HDC hdc, RC FAR *prc, DR3 dr3)
|
|
{
|
|
RC rc;
|
|
|
|
rc = *prc;
|
|
DrawRec3d(hdc, &rc, icvWindowFrame, icvBtnFace, (UINT)(dr3 & dr3All));
|
|
rc.xLeft--;
|
|
rc.yTop--;
|
|
rc.xRight++;
|
|
rc.yBot++;
|
|
DrawRec3d(hdc, &rc, icvBtnShadow, icvBtnHilite, dr3);
|
|
}
|
|
|
|
|
|
static VOID ClipCtlDc(HWND hwnd, HDC hdc)
|
|
{
|
|
RC rc;
|
|
|
|
GetClientRect(hwnd, (LPRECT) &rc);
|
|
IntersectClipRect(hdc, rc.xLeft, rc.yTop, rc.xRight, rc.yBot);
|
|
}
|
|
|
|
|
|
static int IclihkFromHinst(HANDLE hinst)
|
|
{
|
|
int iclihk;
|
|
|
|
for (iclihk = 0; iclihk < g3d.iclihkMac; iclihk++)
|
|
if (g3d.rgclihk[iclihk].hinstApp == hinst)
|
|
return iclihk;
|
|
return -1;
|
|
}
|
|
|
|
|
|
static VOID MyGetTextExtent(HDC hdc, LPTSTR lpsz, int FAR *lpdx, int FAR *lpdy)
|
|
{
|
|
LPTSTR lpch;
|
|
TCHAR szT[256];
|
|
|
|
lpch = szT;
|
|
while(*lpsz != '\000')
|
|
{
|
|
if (*lpsz == '&')
|
|
{
|
|
lpsz++;
|
|
if (*lpsz == '\000')
|
|
break;
|
|
}
|
|
*lpch++ = *lpsz++;
|
|
}
|
|
*lpch = '\000';
|
|
{
|
|
SIZE pt;
|
|
|
|
GetTextExtentPoint(hdc, szT, lstrlen(szT), &pt);
|
|
*lpdx = pt.cx;
|
|
*lpdy = pt.cy;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| CTL3D Publics
|
|
-----------------------------------------------------------------------*/
|
|
|
|
|
|
BOOL WINAPI Ctl3dRegister(HANDLE hinstApp)
|
|
{
|
|
g3d.cInited++;
|
|
if (g3d.cInited == 1)
|
|
{
|
|
Win32Only(LibMain(hinstApp, DLL_PROCESS_ATTACH, (LPVOID) NULL));
|
|
Win16Only(LibMain(hinstApp, 0, 0, (LPSTR) NULL));
|
|
return FInit3dDialogs();
|
|
}
|
|
return g3d.f3dDialogs;
|
|
}
|
|
|
|
|
|
BOOL WINAPI Ctl3dUnregister(HANDLE hinstApp)
|
|
{
|
|
int iclihk;
|
|
|
|
iclihk = IclihkFromHinst(hinstApp);
|
|
if (iclihk != -1)
|
|
{
|
|
Win32Only(UnhookWindowsHookEx(g3d.rgclihk[iclihk].hhook));
|
|
Win16Only(UnhookWindowsHookEx(g3d.rgclihk[iclihk].hhook));
|
|
g3d.iclihkMac--;
|
|
while(iclihk < g3d.iclihkMac)
|
|
{
|
|
g3d.rgclihk[iclihk] = g3d.rgclihk[iclihk+1];
|
|
iclihk++;
|
|
}
|
|
}
|
|
|
|
g3d.cInited--;
|
|
|
|
if (g3d.cInited == 0)
|
|
{
|
|
End3dDialogs();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dAutoSubclass
|
|
|
|
|
| Automatically subclasses all dialogs of the client app.
|
|
|
|
|
| Note: Due to bugs in Commdlg, an app should still call Ctl3dSubclassDlg
|
|
| for the Commdlg OpenFile and PageSetup dialogs.
|
|
|
|
|
| Arguments:
|
|
| HANDLE hinstApp:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
BOOL WINAPI Ctl3dAutoSubclass(HANDLE hinstApp)
|
|
{
|
|
HHOOK hhook;
|
|
HANDLE htask;
|
|
|
|
if (g3d.verWindows < ver31)
|
|
return FALSE;
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
|
|
if (g3d.iclihkMac == ICLIHMAX)
|
|
return FALSE;
|
|
|
|
Win32Only(htask = (HANDLE)GetCurrentThreadId());
|
|
Win32Only(hhook = SetWindowsHookEx(WH_CBT, (HOOKPROC)Ctl3dHook, g3d.hmodLib, (DWORD)htask));
|
|
Win16Only(htask = GetCurrentTask());
|
|
Win16Only(hhook = SetWindowsHookEx(WH_CBT, (HOOKPROC) Ctl3dHook, g3d.hmodLib, (HTASK) (hinstApp == NULL ? NULL : htask)));
|
|
if (hhook != NULL)
|
|
{
|
|
g3d.rgclihk[g3d.iclihkMac].hinstApp = hinstApp;
|
|
g3d.rgclihk[g3d.iclihkMac].htask = htask;
|
|
g3d.rgclihk[g3d.iclihkMac].hhook = hhook;
|
|
g3d.htaskCache = htask;
|
|
g3d.iclihkCache = g3d.iclihkMac;
|
|
g3d.iclihkMac++;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
UINT EXPORT_FUNC Ctl3dSetStyle(HANDLE hinst, LPTSTR lpszName, UINT grbit)
|
|
{
|
|
#ifdef OLD
|
|
UINT grbitOld;
|
|
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
|
|
grbitOld = grbitStyle;
|
|
if (grbit != 0)
|
|
grbitStyle = grbit;
|
|
|
|
if (hinst != NULL && lpszName != NULL)
|
|
{
|
|
HBITMAP hbmpCheckboxesNew;
|
|
|
|
hbmpCheckboxesNew = LoadUIBitmap(hinst, (LPCSTR) lpszName,
|
|
g3d.clrt.rgcv[icvWindowText],
|
|
g3d.clrt.rgcv[icvBtnFace],
|
|
g3d.clrt.rgcv[icvBtnShadow],
|
|
g3d.clrt.rgcv[icvBtnHilite],
|
|
g3d.clrt.rgcv[icvWindow],
|
|
g3d.clrt.rgcv[icvWindowFrame]);
|
|
if (hbmpCheckboxesNew != NULL)
|
|
{
|
|
RemoveGdiObject(&g3d.hbmpCheckboxes);
|
|
g3d.hbmpCheckboxes = hbmpCheckboxesNew;
|
|
}
|
|
}
|
|
|
|
return grbitOld;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dSubclassCtl
|
|
|
|
|
| Subclasses an individual control
|
|
|
|
|
| Arguments:
|
|
| HWND hwnd:
|
|
|
|
|
| Returns:
|
|
| TRUE if control was successfully subclassed
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
BOOL WINAPI Ctl3dSubclassCtl(HWND hwnd)
|
|
{
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
return DoSubclassCtl(hwnd, CTL3D_ALL);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dSubclassDlg
|
|
|
|
|
| Call this during WM_INITDIALOG processing.
|
|
|
|
|
| Arguments:
|
|
| hwndDlg:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
BOOL WINAPI Ctl3dSubclassDlg(HWND hwndDlg, UINT grbit)
|
|
{
|
|
HWND hwnd;
|
|
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
|
|
for(hwnd = GetWindow(hwndDlg, GW_CHILD); hwnd != NULL && IsChild(hwndDlg, hwnd); hwnd = GetWindow(hwnd, GW_HWNDNEXT))
|
|
{
|
|
DoSubclassCtl(hwnd, grbit);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dSubclassDlgEx
|
|
|
|
|
| Call this during WM_INITDIALOG processing. This is like
|
|
| Ctl3dSubclassDlg but it also subclasses the dialog window itself
|
|
| so the app doesn't need to.
|
|
|
|
|
| Arguments:
|
|
| hwndDlg:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
BOOL WINAPI Ctl3dSubclassDlgEx(HWND hwndDlg, DWORD grbit)
|
|
{
|
|
HWND hwnd;
|
|
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
|
|
|
|
for(hwnd = GetWindow(hwndDlg, GW_CHILD); hwnd != NULL && IsChild(hwndDlg, hwnd); hwnd = GetWindow(hwnd, GW_HWNDNEXT))
|
|
{
|
|
DoSubclassCtl(hwnd, LOWORD(grbit));
|
|
}
|
|
|
|
//
|
|
// Now Subclass the dialog window as well
|
|
//
|
|
SubclassWindow((HWND) hwndDlg, (FARPROC)Ctl3dDlgProc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dCtlColor
|
|
|
|
|
| Common CTL_COLOR processor for 3d UITF dialogs & alerts.
|
|
|
|
|
| Arguments:
|
|
| hdc:
|
|
| lParam:
|
|
|
|
|
| Returns:
|
|
| appropriate brush if g3d.f3dDialogs. Returns FALSE otherwise
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
HBRUSH WINAPI Ctl3dCtlColor(HDC hdc, LPARAM lParam)
|
|
{
|
|
#ifdef WIN32
|
|
return (HBRUSH) FALSE;
|
|
#else
|
|
HWND hwndParent;
|
|
|
|
ASSERT(CTLCOLOR_MSGBOX < CTLCOLOR_BTN);
|
|
ASSERT(CTLCOLOR_EDIT < CTLCOLOR_BTN);
|
|
ASSERT(CTLCOLOR_LISTBOX < CTLCOLOR_BTN);
|
|
if(g3d.f3dDialogs)
|
|
{
|
|
if (HIWORD(lParam) >= CTLCOLOR_LISTBOX)
|
|
{
|
|
if (HIWORD(lParam) == CTLCOLOR_LISTBOX &&
|
|
(GetWindow((HWND) LOWORD(lParam), GW_CHILD) == NULL ||
|
|
(GetWindowLong((HWND) LOWORD(lParam), GWL_STYLE) & 0x03) == CBS_DROPDOWNLIST))
|
|
{
|
|
// if it doesn't have a child then it must be a list box
|
|
// don't do brush stuff for drop down lists or else
|
|
// it draws funny grey inside the edit rect
|
|
goto DefWP;
|
|
}
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvBtnText]);
|
|
SetBkColor(hdc, g3d.clrt.rgcv[icvBtnFace]);
|
|
return g3d.brt.mpicvhbr[icvBtnFace];
|
|
}
|
|
}
|
|
DefWP:
|
|
hwndParent = GetParent((HWND) LOWORD(lParam));
|
|
if (hwndParent == NULL)
|
|
return FALSE;
|
|
return (HBRUSH) DefWindowProc(hwndParent, WM_CTLCOLOR, (WPARAM) hdc, (LONG) lParam);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dCtlColorEx
|
|
|
|
|
| Common CTL_COLOR processor for 3d UITF dialogs & alerts.
|
|
|
|
|
| Arguments:
|
|
|
|
|
| Returns:
|
|
| appropriate brush if g3d.f3dDialogs. Returns FALSE otherwise
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
HBRUSH WINAPI Ctl3dCtlColorEx(UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#ifdef WIN32
|
|
ASSERT(WM_CTLCOLORMSGBOX < WM_CTLCOLORBTN);
|
|
ASSERT(WM_CTLCOLOREDIT < WM_CTLCOLORBTN);
|
|
ASSERT(WM_CTLCOLORLISTBOX < WM_CTLCOLORBTN);
|
|
if(g3d.f3dDialogs)
|
|
{
|
|
if (wm >= WM_CTLCOLORLISTBOX && wm != WM_CTLCOLORSCROLLBAR)
|
|
{
|
|
if (wm == WM_CTLCOLORLISTBOX &&
|
|
(GetWindow((HWND) lParam, GW_CHILD) == NULL ||
|
|
(GetWindowLong((HWND) lParam, GWL_STYLE) & 0x03) == CBS_DROPDOWNLIST))
|
|
{
|
|
// if it doesn't have a child then it must be a list box
|
|
// don't do brush stuff for drop down lists or else
|
|
// it draws funny grey inside the edit rect
|
|
return (HBRUSH) FALSE;
|
|
}
|
|
SetTextColor((HDC) wParam, g3d.clrt.rgcv[icvBtnText]);
|
|
SetBkColor((HDC) wParam, g3d.clrt.rgcv[icvBtnFace]);
|
|
return g3d.brt.mpicvhbr[icvBtnFace];
|
|
}
|
|
}
|
|
return (HBRUSH) FALSE;
|
|
#else
|
|
return Ctl3dCtlColor((HDC) wParam, lParam);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dColorChange
|
|
|
|
|
| App calls this when it gets a WM_SYSCOLORCHANGE message
|
|
|
|
|
| Returns:
|
|
| TRUE if successful.
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
BOOL WINAPI Ctl3dColorChange(VOID)
|
|
{
|
|
return InternalCtl3dColorChange(FALSE);
|
|
}
|
|
|
|
LONG WINAPI Ctl3dDlgFramePaint(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LONG lResult;
|
|
LONG lStyle;
|
|
BOOL fBorder;
|
|
|
|
lResult = DefWindowProc(hwnd, wm, wParam, lParam);
|
|
if (!g3d.f3dDialogs)
|
|
return lResult;
|
|
|
|
fBorder = CTL3D_BORDER;
|
|
SendMessage(hwnd, WM_DLGBORDER, 0, (LPARAM)(int FAR *)&fBorder);
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if (fBorder != CTL3D_NOBORDER && (lStyle & (WS_VISIBLE|WS_DLGFRAME|DS_MODALFRAME)) == (WS_VISIBLE|WS_DLGFRAME|DS_MODALFRAME))
|
|
{
|
|
BOOL fCaption;
|
|
HBRUSH hbrSav;
|
|
HDC hdc;
|
|
RC rc;
|
|
RC rcFill;
|
|
int dyFrameTop;
|
|
|
|
fCaption = (lStyle & WS_CAPTION) == WS_CAPTION;
|
|
dyFrameTop = g3d.dyFrame - (fCaption ? dyBorder : 0);
|
|
|
|
hdc = GetWindowDC(hwnd);
|
|
GetWindowRect(hwnd, (LPRECT) &rc);
|
|
rc.xRight = rc.xRight-rc.xLeft;
|
|
rc.yBot = rc.yBot-rc.yTop;
|
|
rc.xLeft = rc.yTop = 0;
|
|
|
|
DrawRec3d(hdc, &rc, icvBtnShadow, icvWindowFrame, dr3All);
|
|
InflateRect((LPRECT) &rc, -dxBorder, -dyBorder);
|
|
DrawRec3d(hdc, &rc, icvBtnHilite, icvBtnShadow, dr3All);
|
|
InflateRect((LPRECT) &rc, -dxBorder, -dyBorder);
|
|
|
|
hbrSav = (HBRUSH) SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnFace]);
|
|
rcFill = rc;
|
|
// Left
|
|
rcFill.xRight = rcFill.xLeft+g3d.dxFrame;
|
|
PatFill(hdc, &rcFill);
|
|
// Right
|
|
OffsetRect((LPRECT) &rcFill, rc.xRight-rc.xLeft-g3d.dxFrame, 0);
|
|
PatFill(hdc, &rcFill);
|
|
// Top
|
|
rcFill.xLeft = rc.xLeft + g3d.dxFrame;
|
|
rcFill.xRight = rc.xRight - g3d.dxFrame;
|
|
rcFill.yBot = rcFill.yTop+dyFrameTop;
|
|
PatFill(hdc, &rcFill);
|
|
if (fCaption)
|
|
{
|
|
RC rcT;
|
|
|
|
rcT = rcFill;
|
|
rcT.yTop += dyFrameTop;
|
|
rcT.yBot = rcT.yTop + g3d.dyCaption;
|
|
DrawRec3d(hdc, &rcT, icvBtnShadow, icvBtnHilite, dr3All);
|
|
}
|
|
|
|
// Bottom
|
|
rcFill.yTop += rc.yBot-rc.yTop-g3d.dxFrame;
|
|
rcFill.yBot = rcFill.yTop + g3d.dyFrame;
|
|
PatFill(hdc, &rcFill);
|
|
#ifdef CHISLEBORDER
|
|
if (fBorder == CTL3D_CHISLEBORDER)
|
|
{
|
|
// This code doesn't work because it draws in the client area
|
|
GetClientRect(hwnd, (LPRECT) &rc);
|
|
OffsetRect((LPRECT) &rc, g3d.dxFrame+2*dxBorder, fCaption ? g3d.dyFrame+g3d.dyCaption : g3d.dyFrame+dyBorder);
|
|
DrawRec3d(hdc, &rc, icvBtnShadow, icvBtnHilite, dr3Bot|dr3Left|dr3Right);
|
|
rc.xLeft++;
|
|
rc.xRight--;
|
|
rc.yBot--;
|
|
DrawRec3d(hdc, &rc, icvBtnHilite, icvBtnShadow, dr3Bot|dr3Left|dr3Right);
|
|
}
|
|
#endif
|
|
SelectObject(hdc, hbrSav);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
return lResult;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| CTL3D Internal Routines
|
|
-----------------------------------------------------------------------*/
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| FInit3dDialogs
|
|
|
|
|
| Initialized 3d stuff
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
static __inline BOOL FInit3dDialogs(VOID)
|
|
{
|
|
HDC hdc;
|
|
WNDCLASS wc;
|
|
extern HANDLE hinstLib;
|
|
|
|
if (g3d.verWindows >= ver40) {
|
|
g3d.f3dDialogs = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
hdc = GetDC(NULL);
|
|
g3d.f3dDialogs =
|
|
GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES) >= 4;
|
|
|
|
// Win 3.1 EGA lies to us...
|
|
|
|
if(GetSystemMetrics(SM_CYSCREEN) == 350 &&
|
|
GetSystemMetrics(SM_CXSCREEN) == 640)
|
|
g3d.f3dDialogs = FALSE;
|
|
ReleaseDC(NULL, hdc);
|
|
if (g3d.f3dDialogs) {
|
|
int ct;
|
|
|
|
#ifdef WIN32
|
|
CodeLpszDecl(lpszC3d, TEXT("C3d"));
|
|
g3d.aCtl3d = GlobalAddAtom(lpszC3d);
|
|
if (g3d.aCtl3d == 0) {
|
|
g3d.f3dDialogs = FALSE;
|
|
return FALSE;
|
|
}
|
|
#else
|
|
CodeLpszDecl(lpszC3dL, "C3dL");
|
|
CodeLpszDecl(lpszC3dH, "C3dH");
|
|
|
|
g3d.aCtl3dLow = GlobalAddAtom(lpszC3dL);
|
|
g3d.aCtl3dHigh = GlobalAddAtom(lpszC3dH);
|
|
if (g3d.aCtl3dLow == 0 || g3d.aCtl3dHigh == 0) {
|
|
g3d.f3dDialogs = FALSE;
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
if (InternalCtl3dColorChange(TRUE)) { // load bitmap & brushes
|
|
for (ct = 0; ct < ctMax; ct++) {
|
|
g3d.mpctctl[ct].lpfn = MakeProcInstance((FARPROC) mpctcdef[ct].lpfnWndProc,
|
|
g3d.hinstLib);
|
|
if (g3d.mpctctl[ct].lpfn == NULL) {
|
|
End3dDialogs();
|
|
return FALSE;
|
|
}
|
|
GetClassInfo(NULL, mpctcdef[ct].sz, (LPWNDCLASS) &wc);
|
|
g3d.mpctctl[ct].lpfnDefProc = wc.lpfnWndProc;
|
|
}
|
|
}
|
|
else
|
|
g3d.f3dDialogs = FALSE;
|
|
}
|
|
return g3d.f3dDialogs;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| End3dDialogs
|
|
|
|
|
| Called at termination to free 3d dialog stuff
|
|
-----------------------------------------------------------------------*/
|
|
static VOID End3dDialogs(VOID)
|
|
{
|
|
int ct;
|
|
|
|
for (ct = 0; ct < ctMax; ct++) {
|
|
if (g3d.mpctctl[ct].lpfn != NULL) {
|
|
FreeProcInstance(g3d.mpctctl[ct].lpfn);
|
|
g3d.mpctctl[ct].lpfn = NULL;
|
|
}
|
|
}
|
|
DeleteObjects();
|
|
g3d.f3dDialogs = FALSE;
|
|
}
|
|
|
|
static BOOL InternalCtl3dColorChange(BOOL fForce)
|
|
{
|
|
ICV icv;
|
|
CLRT clrtNew;
|
|
HBITMAP hbmpCheckboxesNew;
|
|
BRT brtNew;
|
|
|
|
if (!g3d.f3dDialogs)
|
|
return FALSE;
|
|
|
|
for (icv = 0; icv < icvMax; icv++)
|
|
clrtNew.rgcv[icv] = GetSysColor(mpicvSysColor[icv]);
|
|
|
|
if (g3d.verWindows == ver30)
|
|
clrtNew.rgcv[icvBtnHilite] = RGB(0xff, 0xff, 0xff);
|
|
|
|
if (clrtNew.rgcv[icvGrayText] == 0L || clrtNew.rgcv[icvGrayText] == clrtNew.rgcv[icvBtnFace])
|
|
clrtNew.rgcv[icvGrayText] = RGB(0x80, 0x80, 0x80);
|
|
if (clrtNew.rgcv[icvGrayText] == clrtNew.rgcv[icvBtnFace])
|
|
clrtNew.rgcv[icvGrayText] = 0L;
|
|
|
|
if (fForce || _memicmp(&g3d.clrt, &clrtNew, sizeof(CLRT))) {
|
|
hbmpCheckboxesNew =
|
|
LoadUIBitmap(g3d.hinstLib,
|
|
(LPCSTR) MAKEINTRESOURCE(CTL3D_3DCHECK),
|
|
clrtNew.rgcv[icvWindowText],
|
|
clrtNew.rgcv[icvBtnFace],
|
|
clrtNew.rgcv[icvBtnShadow],
|
|
clrtNew.rgcv[icvBtnHilite],
|
|
clrtNew.rgcv[icvWindow],
|
|
clrtNew.rgcv[icvWindowFrame]);
|
|
|
|
for (icv = 0; icv < icvBrushMax; icv++)
|
|
brtNew.mpicvhbr[icv] = CreateSolidBrush(clrtNew.rgcv[icv]);
|
|
|
|
for (icv = 0; icv < icvBrushMax; icv++)
|
|
if (brtNew.mpicvhbr[icv] == NULL)
|
|
goto OOM;
|
|
|
|
if (hbmpCheckboxesNew != NULL) {
|
|
DeleteObjects();
|
|
g3d.brt = brtNew;
|
|
g3d.clrt = clrtNew;
|
|
g3d.hbmpCheckboxes = hbmpCheckboxesNew;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
OOM:
|
|
for (icv = 0; icv < icvBrushMax; icv++)
|
|
RemoveGdiObject(&brtNew.mpicvhbr[icv]);
|
|
RemoveGdiObject(&hbmpCheckboxesNew);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dDlgProc
|
|
|
|
|
| Subclass DlgProc for use w/ Ctl3dAutoSubclass
|
|
|
|
|
|
|
|
| Arguments:
|
|
| HWND hwnd:
|
|
| int wm:
|
|
| UINT wParam:
|
|
| LPARAM lParam:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
LRESULT EXPORT_FUNC Ctl3dDlgProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HBRUSH hbrush;
|
|
FARPROC lpfnDlgProc;
|
|
|
|
switch (wm) {
|
|
case WM_NCDESTROY:
|
|
return CleanupSubclass(hwnd, wm, wParam, lParam, ctMax);
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
LONG l = CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd,ctMax), hwnd, wm, wParam, lParam);
|
|
Ctl3dSubclassDlg(hwnd, (UINT) CTL3D_ALL);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
return l;
|
|
}
|
|
break;
|
|
|
|
case WM_NCPAINT:
|
|
case WM_NCACTIVATE:
|
|
case WM_SETTEXT:
|
|
return Ctl3dDlgFramePaint(hwnd, wm, wParam, lParam);
|
|
break;
|
|
#ifdef WIN32
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORLISTBOX:
|
|
case WM_CTLCOLORMSGBOX:
|
|
case WM_CTLCOLORSTATIC:
|
|
#else
|
|
case WM_CTLCOLOR:
|
|
#endif
|
|
(FARPROC) lpfnDlgProc =
|
|
(FARPROC) GetWindowLong(hwnd, DWL_DLGPROC);
|
|
#ifdef WIN32
|
|
if (lpfnDlgProc == NULL || IsBadReadPtr(lpfnDlgProc, 1))
|
|
hbrush = Ctl3dCtlColorEx(wm, wParam, lParam);
|
|
else {
|
|
hbrush = (HBRUSH) CallWindowProc((WNDPROC) lpfnDlgProc, hwnd, wm, wParam, lParam);
|
|
// hbrush = (HBRUSH) (*lpfnDlgProc)(hwnd, wm, wParam, lParam);
|
|
if (hbrush == (HBRUSH) FALSE || hbrush == (HBRUSH)1)
|
|
hbrush = Ctl3dCtlColorEx(wm, wParam, lParam);
|
|
}
|
|
#else
|
|
if (lpfnDlgProc == NULL)
|
|
hbrush = Ctl3dCtlColorEx(wm, wParam, lParam);
|
|
else {
|
|
hbrush = (HBRUSH) CallWindowProc((WNDPROC) lpfnDlgProc, hwnd, wm, wParam, lParam);
|
|
// hbrush = (HBRUSH) (*lpfnDlgProc)(hwnd, wm, wParam, lParam);
|
|
if (!hbrush || hbrush == (HBRUSH)1)
|
|
hbrush = Ctl3dCtlColorEx(wm, wParam, lParam);
|
|
}
|
|
#endif
|
|
if (hbrush)
|
|
return (LRESULT) (UINT) hbrush;
|
|
break;
|
|
}
|
|
return CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ctMax), hwnd, wm, wParam, lParam);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Ctl3dHook
|
|
|
|
|
| CBT Hook to watch for window creation. Automatically subclasses all
|
|
| dialogs w/ Ctl3dDlgProc
|
|
|
|
|
| Arguments:
|
|
| int code:
|
|
| UINT wParam:
|
|
| LPARAM lParam:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
LRESULT EXPORT_FUNC Ctl3dHook(int code, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static HWND hwndHookDlg = NULL;
|
|
int iclihk;
|
|
HANDLE htask;
|
|
|
|
if (code == HCBT_CREATEWND)
|
|
{
|
|
LPCREATESTRUCT lpcs;
|
|
|
|
lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
|
|
if (lpcs->lpszClass == WC_DIALOG )
|
|
{
|
|
hwndHookDlg = (HWND) wParam;
|
|
}
|
|
else if (hwndHookDlg != NULL)
|
|
{
|
|
BOOL fSubclass;
|
|
|
|
fSubclass = TRUE;
|
|
SendMessage((HWND) hwndHookDlg, WM_DLGSUBCLASS, 0, (LPARAM)(UINT FAR *)&fSubclass);
|
|
if (fSubclass)
|
|
{
|
|
lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
|
|
if ( lpcs->hwndParent == hwndHookDlg )
|
|
SubclassWindow(hwndHookDlg, (FARPROC) Ctl3dDlgProc);
|
|
else
|
|
hwndHookDlg = NULL;
|
|
}
|
|
hwndHookDlg = NULL;
|
|
}
|
|
}
|
|
|
|
htask = Win32Or16((HANDLE)GetCurrentThreadId(), GetCurrentTask());
|
|
if (htask != g3d.htaskCache)
|
|
{
|
|
for (iclihk = 0; iclihk < g3d.iclihkMac; iclihk++)
|
|
{
|
|
if (g3d.rgclihk[iclihk].htask == htask)
|
|
{
|
|
g3d.iclihkCache = iclihk;
|
|
g3d.htaskCache = htask;
|
|
break;
|
|
}
|
|
}
|
|
// didn't find task in hook table. This could be bad, but
|
|
// returning 0L is about all we can doo.
|
|
return 0L;
|
|
}
|
|
Win32Only(return CallNextHookEx(g3d.rgclihk[g3d.iclihkCache].hhook, code, wParam, lParam));
|
|
Win16Only(return (CallNextHookEx(g3d.rgclihk[g3d.iclihkCache].hhook, code, wParam, lParam)));
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| CTL3D F* routines
|
|
|
|
|
| These routines determine whether or not the given control may be
|
|
| subclassed. They may recursively call DoSubclassCtl in the
|
|
| case of multi-control controls
|
|
|
|
|
| Returns:
|
|
| TRUE if can subclass the given control.
|
|
-----------------------------------------------------------------------*/
|
|
|
|
|
|
static BOOL FBtn(HWND hwnd, LONG style, UINT grbit)
|
|
{
|
|
return ( LOWORD(style) >= BS_PUSHBUTTON && LOWORD(style) <= BS_AUTORADIOBUTTON);
|
|
}
|
|
|
|
static BOOL FEdit(HWND hwnd, LONG style, UINT grbit)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL FList(HWND hwnd, LONG style, UINT grbit)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL FCombo(HWND hwnd, LONG style, UINT grbit)
|
|
{
|
|
HWND hwndEdit;
|
|
HWND hwndList;
|
|
|
|
if ((style & 0x0003) == CBS_SIMPLE)
|
|
{
|
|
hwndList = GetWindow(hwnd, GW_CHILD);
|
|
if (hwndList != NULL)
|
|
{
|
|
// Subclass list & edit box so they draw properly. We also
|
|
// subclass the combo so we can hide/show/move it and the
|
|
// 3d effects outside the client area get erased
|
|
DoSubclassCtl(hwndList, CTL3D_LISTBOXES);
|
|
|
|
hwndEdit = GetWindow(hwndList, GW_HWNDNEXT);
|
|
if (hwndEdit != NULL)
|
|
DoSubclassCtl(hwndEdit, CTL3D_EDITS);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
else if ((style & 0x0003) == CBS_DROPDOWN)
|
|
{
|
|
// Subclass edit so bottom border of the edit draws properly...This case
|
|
// is specially handled in ListEditPaint3d
|
|
hwndEdit = GetWindow(hwnd, GW_CHILD);
|
|
if (hwndEdit != NULL)
|
|
DoSubclassCtl(hwndEdit, CTL3D_EDITS);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL FStatic(HWND hwnd, LONG style, UINT grbit)
|
|
{
|
|
int wStyle;
|
|
wStyle = LOWORD(style) & 0xf;
|
|
return (wStyle != SS_ICON &&
|
|
((grbit & CTL3D_STATICTEXTS) &&
|
|
(wStyle <= SS_RIGHT || wStyle == SS_LEFTNOWORDWRAP) ||
|
|
((grbit & CTL3D_STATICFRAMES) &&
|
|
(wStyle >= SS_BLACKRECT && wStyle <= SS_WHITEFRAME))));
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| DoSubclassCtl
|
|
|
|
|
| Actually subclass the control
|
|
|
|
|
|
|
|
| Arguments:
|
|
| HWND hwnd:
|
|
| UINT grbit:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
static BOOL DoSubclassCtl(HWND hwnd, UINT grbit)
|
|
{
|
|
LONG style;
|
|
int ct;
|
|
BOOL fCan;
|
|
TCHAR szClass[64];
|
|
|
|
// Is this already subclassed by CTL3D?
|
|
if (LpfnGetDefWndProcNull(hwnd) != (FARPROC) NULL)
|
|
return FALSE;
|
|
|
|
GetClassName(hwnd, szClass, sizeof(szClass));
|
|
|
|
for (ct = 0; ct < ctMax; ct++)
|
|
{
|
|
if ((mpctcdef[ct].msk & grbit) &&
|
|
(lstrcmp(mpctcdef[ct].sz,szClass) == 0))
|
|
{
|
|
style = GetWindowLong(hwnd, GWL_STYLE);
|
|
fCan = mpctcdef[ct].lpfnFCanSubclass(hwnd, style, grbit);
|
|
if (fCan == TRUE)
|
|
{
|
|
SubclassWindow(hwnd, g3d.mpctctl[ct].lpfn);
|
|
}
|
|
return fCan != FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| Inval3dCtl
|
|
|
|
|
| Invalidate the controls rect in response to a WM_SHOWWINDOW or
|
|
| WM_WINDOWPOSCHANGING message. This is necessary because ctl3d draws
|
|
| the 3d effects of listboxes, combos & edits outside the controls client
|
|
| rect.
|
|
|
|
|
| Arguments:
|
|
| HWND hwnd:
|
|
| WINDOWPOS FAR *lpwp:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
static VOID Inval3dCtl(HWND hwnd, WINDOWPOS FAR *lpwp)
|
|
{
|
|
RC rc;
|
|
HWND hwndParent;
|
|
LONG lStyle;
|
|
|
|
GetWindowRect(hwnd, (LPRECT) &rc);
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if (lStyle & WS_VISIBLE)
|
|
{
|
|
if (lpwp != NULL)
|
|
{
|
|
unsigned flags;
|
|
|
|
// handle integral height listboxes (or any other control which
|
|
// shrinks from the bottom)
|
|
flags = lpwp->flags;
|
|
if ((flags & (SWP_NOMOVE|SWP_NOSIZE)) == SWP_NOMOVE &&
|
|
(lpwp->cx == (rc.xRight-rc.xLeft) && lpwp->cy <= (rc.yBot-rc.yTop)))
|
|
rc.yTop = rc.yTop+lpwp->cy+1; // +1 to offset InflateRect
|
|
}
|
|
InflateRect((LPRECT) &rc, 1, 1);
|
|
hwndParent = GetParent(hwnd);
|
|
ScreenToClient(hwndParent, (LPPOINT) &rc);
|
|
ScreenToClient(hwndParent, ((LPPOINT) &rc)+1);
|
|
if(lStyle & WS_VSCROLL)
|
|
rc.xRight ++;
|
|
InvalidateRect(hwndParent, (LPRECT) &rc, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| CTL3D Subclass Wndprocs
|
|
-----------------------------------------------------------------------*/
|
|
|
|
// These values are assumed for bit shifting operations
|
|
|
|
#define BFCHECK 0x0003
|
|
#define BFSTATE 0x0004
|
|
#define BFFOCUS 0x0008
|
|
#define BFINCLICK 0x0010 // Inside click code
|
|
#define BFCAPTURED 0x0020 // We have mouse capture
|
|
#define BFMOUSE 0x0040 // Mouse-initiated
|
|
#define BFDONTCLICK 0x0080 // Don't check on get focus
|
|
|
|
#define bpText 0x0002
|
|
#define bpCheck 0x0004
|
|
#define bpFocus 0x0008 // must be same as BFFOCUS
|
|
#define bpBkgnd 0x0010
|
|
#define bpEraseGroupText 0x0020
|
|
|
|
static VOID DrawPushButton(HWND hwnd, HDC hdc, RC FAR *lprc, LPTSTR lpch, int cch, UINT bs, BOOL fDown)
|
|
{
|
|
int dxyBrdr;
|
|
int dxyShadow;
|
|
HBRUSH hbrSav;
|
|
RC rcInside;
|
|
rcInside = *lprc;
|
|
|
|
// if (!(grbitStyle & bitFCoolButtons))
|
|
{
|
|
DrawRec3d(hdc, lprc, icvWindowFrame, icvWindowFrame, dr3All);
|
|
InflateRect((LPRECT) &rcInside, -1, -1);
|
|
if (bs == LOWORD(BS_DEFPUSHBUTTON) && IsWindowEnabled(hwnd))
|
|
{
|
|
dxyBrdr = 2;
|
|
DrawRec3d(hdc, &rcInside, icvWindowFrame, icvWindowFrame, dr3All);
|
|
InflateRect((LPRECT) &rcInside, -1, -1);
|
|
}
|
|
else
|
|
dxyBrdr = 1;
|
|
|
|
// Notch the corners
|
|
PatBlt(hdc, lprc->xLeft, lprc->yTop, dxBorder, dyBorder, PATCOPY);
|
|
/* Top xRight corner */
|
|
PatBlt(hdc, lprc->xRight - dxBorder, lprc->yTop, dxBorder, dyBorder, PATCOPY);
|
|
/* yBot xLeft corner */
|
|
PatBlt(hdc, lprc->xLeft, lprc->yBot - dyBorder, dxBorder, dyBorder, PATCOPY);
|
|
/* yBot xRight corner */
|
|
PatBlt(hdc, lprc->xRight - dxBorder, lprc->yBot - dyBorder, dxBorder, dyBorder, PATCOPY);
|
|
dxyShadow = 1 + !fDown;
|
|
}
|
|
// else
|
|
// dxyShadow = 1;
|
|
|
|
// draw upper left hilite/shadow
|
|
|
|
if (fDown)
|
|
hbrSav = (HBRUSH) SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnShadow]);
|
|
else
|
|
hbrSav = (HBRUSH) SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnHilite]);
|
|
|
|
PatBlt(hdc, rcInside.xLeft, rcInside.yTop, dxyShadow,
|
|
(rcInside.yBot - rcInside.yTop), PATCOPY);
|
|
PatBlt(hdc, rcInside.xLeft, rcInside.yTop,
|
|
(rcInside.xRight - rcInside.xLeft), dxyShadow, PATCOPY);
|
|
|
|
// draw lower right shadow (only if not down)
|
|
if (!fDown) // || (grbitStyle & bitFCoolButtons))
|
|
{
|
|
int i;
|
|
|
|
if (fDown)
|
|
SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnHilite]);
|
|
else
|
|
SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnShadow]);
|
|
|
|
rcInside.yBot--;
|
|
rcInside.xRight--;
|
|
|
|
for (i = 0; i < dxyShadow; i++)
|
|
{
|
|
PatBlt(hdc, rcInside.xLeft, rcInside.yBot,
|
|
rcInside.xRight - rcInside.xLeft + dxBorder, dyBorder,
|
|
PATCOPY);
|
|
PatBlt(hdc, rcInside.xRight, rcInside.yTop, dxBorder,
|
|
rcInside.yBot - rcInside.yTop, PATCOPY);
|
|
if (i < dxyShadow-1)
|
|
InflateRect((LPRECT) &rcInside, -dxBorder, -dyBorder);
|
|
}
|
|
}
|
|
// draw the button face
|
|
|
|
rcInside.xLeft++;
|
|
rcInside.yTop++;
|
|
|
|
SelectObject(hdc, g3d.brt.mpicvhbr[icvBtnFace]);
|
|
PatBlt(hdc, rcInside.xLeft, rcInside.yTop, rcInside.xRight-rcInside.xLeft,
|
|
rcInside.yBot - rcInside.yTop, PATCOPY);
|
|
|
|
// Draw the durned text
|
|
|
|
if(!IsWindowEnabled(hwnd))
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvGrayText]);
|
|
|
|
{
|
|
int dy;
|
|
int dx;
|
|
|
|
MyGetTextExtent(hdc, lpch, &dx, &dy);
|
|
rcInside.yTop += (rcInside.yBot-rcInside.yTop-dy)/2;
|
|
rcInside.xLeft += (rcInside.xRight-rcInside.xLeft-dx)/2;
|
|
rcInside.yBot = min(rcInside.yTop+dy, rcInside.yBot);
|
|
rcInside.xRight = min(rcInside.xLeft+dx, rcInside.xRight);
|
|
}
|
|
|
|
if (fDown)
|
|
{
|
|
OffsetRect((LPRECT) &rcInside, 1, 1);
|
|
rcInside.xRight = min(rcInside.xRight, lprc->xRight-3);
|
|
rcInside.yBot = min(rcInside.yBot, lprc->yBot-3);
|
|
}
|
|
|
|
DrawText(hdc, lpch, cch, (LPRECT) &rcInside, DT_LEFT|DT_SINGLELINE);
|
|
|
|
if (hwnd == GetFocus())
|
|
{
|
|
InflateRect((LPRECT) &rcInside, 1, 1);
|
|
IntersectRect((LPRECT) &rcInside, (LPRECT) &rcInside, (LPRECT) lprc);
|
|
DrawFocusRect(hdc, (LPRECT) &rcInside);
|
|
}
|
|
|
|
if (hbrSav)
|
|
SelectObject(hdc, hbrSav);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| BtnPaint
|
|
|
|
|
| Paint a button
|
|
|
|
|
| Arguments:
|
|
| HWND hwnd:
|
|
| HDC hdc:
|
|
| int bp:
|
|
|
|
|
| Returns:
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
static VOID BtnPaint(HWND hwnd, HDC hdc, int bp)
|
|
{
|
|
RC rc;
|
|
RC rcClient;
|
|
HFONT hfont;
|
|
int bs;
|
|
int bf;
|
|
HBRUSH hbrBtn;
|
|
HWND hwndParent;
|
|
int xBtnBmp;
|
|
int yBtnBmp;
|
|
HBITMAP hbmpSav;
|
|
HDC hdcMem;
|
|
TCHAR szTitle[256];
|
|
int cch;
|
|
BOOL fEnabled;
|
|
|
|
bs = ((int) GetWindowLong(hwnd, GWL_STYLE)) & Win32Or16(0x0000001F, 0x001F);
|
|
hwndParent = GetParent(hwnd);
|
|
SetBkMode(hdc, OPAQUE);
|
|
GetClientRect(hwnd, (LPRECT)&rcClient);
|
|
rc = rcClient;
|
|
if((hfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L)) != NULL)
|
|
hfont = (HFONT) SelectObject(hdc, hfont);
|
|
|
|
hbrBtn = SEND_COLOR_BUTTON_MESSAGE(hwndParent, hwnd, hdc);
|
|
hbrBtn = (HBRUSH) SelectObject(hdc, hbrBtn);
|
|
IntersectClipRect(hdc, rc.xLeft, rc.yTop, rc.xRight, rc.yBot);
|
|
if(bp & bpBkgnd && (bs != BS_GROUPBOX))
|
|
PatBlt(hdc, rc.xLeft, rc.yTop, rc.xRight-rc.xLeft, rc.yBot-rc.yTop, PATCOPY);
|
|
|
|
fEnabled = IsWindowEnabled(hwnd);
|
|
bf = (int) SendMessage(hwnd, BM_GETSTATE, 0, 0L);
|
|
yBtnBmp = 0;
|
|
xBtnBmp = (((bf&BFCHECK) != 0) | ((bf&BFSTATE) >> 1)) * 14;
|
|
if (!fEnabled)
|
|
xBtnBmp += 14*(2+((bf&BFCHECK) != 0));
|
|
if(bp & (bpText|bpFocus) ||
|
|
bs == BS_PUSHBUTTON || bs == BS_DEFPUSHBUTTON)
|
|
cch = GetWindowText(hwnd, szTitle, sizeof(szTitle));
|
|
switch(bs)
|
|
{
|
|
#ifdef DEBUG
|
|
default:
|
|
ASSERT(FALSE);
|
|
break;
|
|
#endif
|
|
case BS_PUSHBUTTON:
|
|
case BS_DEFPUSHBUTTON:
|
|
DrawPushButton(hwnd, hdc, &rcClient, szTitle, cch, LOWORD(bs), bf & BFSTATE);
|
|
break;
|
|
|
|
case BS_RADIOBUTTON:
|
|
case BS_AUTORADIOBUTTON:
|
|
yBtnBmp = 13;
|
|
goto DrawBtn;
|
|
case BS_3STATE:
|
|
case BS_AUTO3STATE:
|
|
ASSERT((BFSTATE >> 1) == 2);
|
|
if((bf & BFCHECK) == 2)
|
|
yBtnBmp = 26;
|
|
// fall through
|
|
case BS_CHECKBOX:
|
|
case BS_AUTOCHECKBOX:
|
|
DrawBtn:
|
|
if(bp & bpCheck)
|
|
{
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
if(hdcMem != NULL)
|
|
{
|
|
hbmpSav = (HBITMAP) SelectObject(hdcMem, g3d.hbmpCheckboxes);
|
|
if(hbmpSav != NULL)
|
|
{
|
|
BitBlt(hdc, rc.xLeft, rc.yTop+(rc.yBot-rc.yTop-13)/2,
|
|
14, 13, hdcMem, xBtnBmp, yBtnBmp, SRCCOPY);
|
|
SelectObject(hdcMem, hbmpSav);
|
|
}
|
|
DeleteDC(hdcMem);
|
|
}
|
|
}
|
|
if(bp & bpText)
|
|
{
|
|
// BUG! this assumes we have only 1 hbm3dCheck type
|
|
rc.xLeft = rcClient.xLeft + 14+4;
|
|
if(!fEnabled)
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvGrayText]);
|
|
DrawText(hdc, szTitle, cch, (LPRECT) &rc, DT_VCENTER|DT_LEFT|DT_SINGLELINE);
|
|
}
|
|
if(bp & bpFocus)
|
|
{
|
|
int dx;
|
|
int dy;
|
|
|
|
MyGetTextExtent(hdc, szTitle, &dx, &dy);
|
|
rc.yTop = (rc.yBot-rc.yTop-dy)/2;
|
|
rc.yBot = rc.yTop+dy;
|
|
rc.xLeft = rcClient.xLeft + 14+4;
|
|
rc.xRight = rc.xLeft + dx;
|
|
InflateRect((LPRECT) &rc, 1, 1);
|
|
IntersectRect((LPRECT) &rc, (LPRECT) &rc, (LPRECT) &rcClient);
|
|
DrawFocusRect(hdc, (LPRECT) &rc);
|
|
}
|
|
break;
|
|
case BS_GROUPBOX:
|
|
if(bp & (bpText|bpCheck))
|
|
{
|
|
int dy;
|
|
int dx;
|
|
|
|
MyGetTextExtent(hdc, szTitle, &dx, &dy);
|
|
if (dy == 0)
|
|
{
|
|
int dxT;
|
|
MyGetTextExtent(hdc, TEXT("X"), &dxT, &dy);
|
|
}
|
|
|
|
rc.xLeft += 4;
|
|
rc.xRight = rc.xLeft + dx + 4;
|
|
rc.yBot = rc.yTop + dy;
|
|
|
|
if (bp & bpEraseGroupText)
|
|
{
|
|
RC rcT;
|
|
|
|
rcT = rc;
|
|
rcT.xRight = rcClient.xRight;
|
|
// Hack!
|
|
ClientToScreen(hwnd, (LPPOINT) &rcT);
|
|
ClientToScreen(hwnd, ((LPPOINT) &rcT)+1);
|
|
ScreenToClient(hwndParent, (LPPOINT) &rcT);
|
|
ScreenToClient(hwndParent, ((LPPOINT) &rcT)+1);
|
|
InvalidateRect(hwndParent, (LPRECT) &rcT, TRUE);
|
|
return;
|
|
}
|
|
|
|
rcClient.yTop += dy/2;
|
|
rcClient.xRight--;
|
|
rcClient.yBot--;
|
|
DrawRec3d(hdc, &rcClient, icvBtnShadow, icvBtnShadow, dr3All);
|
|
OffsetRect((LPRECT) &rcClient, 1, 1);
|
|
DrawRec3d(hdc, &rcClient, icvBtnHilite, icvBtnHilite, dr3All);
|
|
|
|
if(!fEnabled)
|
|
SetTextColor(hdc, g3d.clrt.rgcv[icvGrayText]);
|
|
DrawText(hdc, szTitle, cch, (LPRECT) &rc, DT_LEFT|DT_SINGLELINE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
SelectObject(hdc, hbrBtn);
|
|
if(hfont != NULL)
|
|
SelectObject(hdc, hfont);
|
|
}
|
|
|
|
LRESULT EXPORT_FUNC BtnWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LONG lRet;
|
|
LONG lStyle;
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
int bf;
|
|
int bfNew;
|
|
int bp;
|
|
|
|
switch(wm)
|
|
{
|
|
case WM_NCDESTROY:
|
|
return CleanupSubclass(hwnd, wm, wParam, lParam, ctButton);
|
|
|
|
case WM_SETTEXT:
|
|
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if ((lStyle & WS_VISIBLE) && (LOWORD(lStyle) & 0x1f) == BS_GROUPBOX)
|
|
{
|
|
// total hack -- if group box text length shortens then
|
|
// we have to erase the old text. BtnPaint will Invalidate
|
|
// the rect of the text so everything will redraw.
|
|
bp = bpText | bpEraseGroupText;
|
|
}
|
|
else
|
|
{
|
|
bp = bpText|bpCheck|bpBkgnd;
|
|
}
|
|
goto DoIt;
|
|
break;
|
|
|
|
case BM_SETSTATE:
|
|
case BM_SETCHECK:
|
|
bp = bpCheck;
|
|
goto DoIt;
|
|
case WM_KILLFOCUS:
|
|
// HACK! Windows will go into an infinite loop trying to sync the
|
|
// states of the AUTO_RADIOBUTTON in this group. (we turn off the
|
|
// visible bit so it gets skipped in the enumeration)
|
|
// Disable this code by clearing the STATE bit
|
|
if ((LOWORD(GetWindowLong(hwnd, GWL_STYLE)) & 0x1F) == BS_AUTORADIOBUTTON)
|
|
SendMessage(hwnd, BM_SETSTATE, 0, 0L);
|
|
bp = 0;
|
|
goto DoIt;
|
|
case WM_ENABLE:
|
|
bp = bpCheck | bpText;
|
|
goto DoIt;
|
|
case WM_SETFOCUS:
|
|
// HACK! if wParam == NULL we may be activated via the task manager
|
|
// Erase background of control because a WM_ERASEBKGND messsage has not
|
|
// arrived yet for the dialog
|
|
bp = wParam == (WPARAM)NULL ? (bpCheck | bpText | bpBkgnd) : (bpCheck | bpText);
|
|
DoIt:
|
|
bf = (int) SendMessage(hwnd, BM_GETSTATE, 0, 0L);
|
|
if((lStyle = GetWindowLong(hwnd, GWL_STYLE)) & WS_VISIBLE)
|
|
{
|
|
SetWindowLong(hwnd, GWL_STYLE, lStyle & ~(WS_VISIBLE));
|
|
lRet = CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ctButton), hwnd, wm, wParam, lParam);
|
|
|
|
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE)|WS_VISIBLE);
|
|
bfNew = (int) SendMessage(hwnd, BM_GETSTATE, 0, 0L);
|
|
if((wm != BM_SETSTATE && wm != BM_SETCHECK) ||
|
|
bf != bfNew)
|
|
{
|
|
hdc = GetDC(hwnd);
|
|
if (hdc != NULL)
|
|
{
|
|
ASSERT(BFFOCUS == bpFocus);
|
|
/* If the check state changed, redraw no matter what,
|
|
because it won't have during the above call to the def
|
|
wnd proc */
|
|
if ((bf & BFCHECK) != (bfNew & BFCHECK))
|
|
bp |= bpCheck;
|
|
ExcludeUpdateRgn(hdc, hwnd);
|
|
BtnPaint(hwnd, hdc, bp|((bf^bfNew)&BFFOCUS));
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
}
|
|
return lRet;
|
|
}
|
|
break;
|
|
case WM_PAINT:
|
|
bf = (int) SendMessage(hwnd, BM_GETSTATE, 0, 0L);
|
|
if ((hdc = (HDC) wParam) == NULL)
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
if(GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE)
|
|
BtnPaint(hwnd, hdc, bpText|bpCheck|(bf&BFFOCUS));
|
|
if (wParam == (WPARAM)NULL)
|
|
EndPaint(hwnd, &ps);
|
|
return 0L;
|
|
}
|
|
return CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ctButton), hwnd, wm, wParam, lParam);
|
|
}
|
|
|
|
|
|
void ListEditPaint3d(HWND hwnd, BOOL fEdit, int ct)
|
|
{
|
|
CTLID id;
|
|
RC rc;
|
|
HDC hdc;
|
|
HWND hwndParent;
|
|
LONG lStyle;
|
|
DR3 dr3;
|
|
|
|
if(!((lStyle = GetWindowLong(hwnd, GWL_STYLE)) & WS_VISIBLE))
|
|
return;
|
|
|
|
if (fEdit)
|
|
HideCaret(hwnd);
|
|
|
|
GetWindowRect(hwnd, (LPRECT) &rc);
|
|
|
|
ScreenToClient(hwndParent = GetParent(hwnd), (LPPOINT) &rc);
|
|
ScreenToClient(hwndParent, ((LPPOINT) &rc)+1);
|
|
|
|
hdc = GetDC(hwndParent);
|
|
|
|
if(lStyle & WS_VSCROLL)
|
|
dr3 = dr3All & ~dr3Right;
|
|
else
|
|
dr3 = dr3All;
|
|
|
|
// don't draw the top if it's a listbox of a simple combo
|
|
id = GetControlId(hwnd);
|
|
if (id == (CTLID) (1000 + fEdit))
|
|
{
|
|
TCHAR szClass[10];
|
|
|
|
// could be subclassed!
|
|
GetClassName(hwndParent, szClass, sizeof(szClass));
|
|
if (!lstrcmp(szClass, mpctcdef[ctCombo].sz))
|
|
{
|
|
if (fEdit)
|
|
{
|
|
RC rcList;
|
|
HWND hwndList;
|
|
if ((GetWindowLong(hwndParent, GWL_STYLE) & 0x0003) == CBS_SIMPLE)
|
|
{
|
|
dr3 &= ~dr3Bot;
|
|
|
|
hwndList = GetWindow(hwndParent, GW_CHILD);
|
|
GetWindowRect(hwndList, (LPRECT) &rcList);
|
|
|
|
// Some ugly shit goin' on here!
|
|
rc.xRight -= rcList.xRight-rcList.xLeft;
|
|
DrawInsetRect3d(hdc, &rc, dr3Bot|dr3HackBotRight);
|
|
rc.xRight += rcList.xRight-rcList.xLeft;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc.yTop++;
|
|
dr3 &= ~dr3Top;
|
|
}
|
|
}
|
|
}
|
|
|
|
DrawInsetRect3d(hdc, &rc, dr3);
|
|
|
|
if ((ct == ctCombo && (lStyle & 0x003) == CBS_DROPDOWNLIST))
|
|
{
|
|
rc.xLeft = rc.xRight - GetSystemMetrics(SM_CXVSCROLL);
|
|
DrawRec3d(hdc, &rc, icvWindowFrame, icvWindowFrame, dr3Right|dr3Bot);
|
|
}
|
|
else if (lStyle & WS_VSCROLL)
|
|
{
|
|
rc.xRight++;
|
|
DrawRec3d(hdc, &rc, icvBtnHilite, icvBtnHilite, dr3Right);
|
|
rc.xRight--;
|
|
rc.xLeft = rc.xRight - GetSystemMetrics(SM_CXVSCROLL);
|
|
DrawRec3d(hdc, &rc, icvWindowFrame, icvWindowFrame, dr3Bot);
|
|
}
|
|
|
|
ReleaseDC(hwndParent, hdc);
|
|
if (fEdit)
|
|
ShowCaret(hwnd);
|
|
}
|
|
|
|
|
|
LONG ShareEditComboWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam, int ct)
|
|
{
|
|
LONG l;
|
|
|
|
l = CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd,ct), hwnd, wm, wParam, lParam);
|
|
switch(wm)
|
|
{
|
|
case WM_NCDESTROY:
|
|
// Can't use clean up subclass here because already called defproc
|
|
|
|
Win32Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3d));
|
|
Win16Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3dLow));
|
|
Win16Only(RemoveProp(hwnd, (LPCTSTR) g3d.aCtl3dHigh));
|
|
break;
|
|
|
|
case WM_SHOWWINDOW:
|
|
if (g3d.verWindows < ver31 && wParam == 0)
|
|
Inval3dCtl(hwnd, (WINDOWPOS FAR *) NULL);
|
|
break;
|
|
case WM_WINDOWPOSCHANGING:
|
|
if (g3d.verWindows >= ver31)
|
|
Inval3dCtl(hwnd, (WINDOWPOS FAR *) lParam);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if (ct != ctCombo || (GetWindowLong(hwnd, GWL_STYLE) & 0x0003) != CBS_SIMPLE)
|
|
ListEditPaint3d(hwnd, TRUE, ct);
|
|
break;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
LRESULT EXPORT_FUNC EditWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return ShareEditComboWndProc3d(hwnd, wm, wParam, lParam, ctEdit);
|
|
}
|
|
|
|
|
|
LONG SharedListWndProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam, unsigned ct)
|
|
{
|
|
LONG l;
|
|
switch(wm)
|
|
{
|
|
case WM_NCDESTROY:
|
|
return CleanupSubclass(hwnd, wm, wParam, lParam, ct);
|
|
|
|
case WM_SHOWWINDOW:
|
|
if (g3d.verWindows < ver31 && wParam == 0)
|
|
Inval3dCtl(hwnd, (WINDOWPOS FAR *) NULL);
|
|
break;
|
|
case WM_WINDOWPOSCHANGING:
|
|
if (g3d.verWindows >= ver31)
|
|
Inval3dCtl(hwnd, (WINDOWPOS FAR *) lParam);
|
|
break;
|
|
case WM_PAINT:
|
|
l = CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ct), hwnd, wm, wParam, lParam);
|
|
ListEditPaint3d(hwnd, FALSE, ct);
|
|
return l;
|
|
case WM_NCCALCSIZE:
|
|
{
|
|
RC rc;
|
|
RC rcNew;
|
|
HWND hwndParent;
|
|
|
|
// Inval3dCtl handles this case under Win 3.1
|
|
if (g3d.verWindows >= ver31)
|
|
break;
|
|
|
|
GetWindowRect(hwnd, (LPRECT) &rc);
|
|
#ifdef UNREACHABLE
|
|
if (g3d.verWindows >= ver31)
|
|
{
|
|
hwndParent = GetParent(hwnd);
|
|
ScreenToClient(hwndParent, (LPPOINT) &rc);
|
|
ScreenToClient(hwndParent, ((LPPOINT) &rc)+1);
|
|
}
|
|
#endif
|
|
|
|
l = CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ct), hwnd, wm, wParam, lParam);
|
|
|
|
rcNew = *(RC FAR *)lParam;
|
|
InflateRect((LPRECT) &rcNew, 2, 1); // +1 for border (Should use AdjustWindowRect)
|
|
if (rcNew.yBot < rc.yBot)
|
|
{
|
|
rcNew.yTop = rcNew.yBot+1;
|
|
rcNew.yBot = rc.yBot+1;
|
|
|
|
#ifdef ALWAYS
|
|
if (g3d.verWindows < ver31)
|
|
#endif
|
|
{
|
|
hwndParent = GetParent(hwnd);
|
|
ScreenToClient(hwndParent, (LPPOINT) &rcNew);
|
|
ScreenToClient(hwndParent, ((LPPOINT) &rcNew)+1);
|
|
}
|
|
|
|
InvalidateRect(hwndParent, (LPRECT) &rcNew, TRUE);
|
|
}
|
|
return l;
|
|
}
|
|
break;
|
|
}
|
|
return CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ct), hwnd, wm, wParam, lParam);
|
|
}
|
|
|
|
LRESULT EXPORT_FUNC ListWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return SharedListWndProc(hwnd, wm, wParam, lParam, ctList);
|
|
}
|
|
|
|
LRESULT EXPORT_FUNC ComboWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return ShareEditComboWndProc3d(hwnd, wm, wParam, lParam, ctCombo);
|
|
}
|
|
|
|
void StaticPrint(HWND hwnd, HDC hdc, RC FAR *lprc, LONG style)
|
|
{
|
|
UINT dt;
|
|
LONG cv;
|
|
int cch;
|
|
TCHAR szText[512];
|
|
|
|
PatBlt(hdc, lprc->xLeft, lprc->yTop, lprc->xRight-lprc->xLeft, lprc->yBot-lprc->yTop, PATCOPY);
|
|
|
|
if ((cch = GetWindowText(hwnd, szText, sizeof(szText))) == 0)
|
|
return;
|
|
|
|
if ((style & 0x000f) == SS_LEFTNOWORDWRAP)
|
|
dt = DT_NOCLIP | DT_EXPANDTABS;
|
|
else
|
|
{
|
|
dt = LOWORD(DT_NOCLIP | DT_EXPANDTABS | DT_WORDBREAK | ((style & 0x0000000f)-SS_LEFT));
|
|
}
|
|
|
|
if (style & SS_NOPREFIX)
|
|
dt |= DT_NOPREFIX;
|
|
|
|
if (style & WS_DISABLED)
|
|
cv = SetTextColor(hdc, g3d.clrt.rgcv[icvGrayText]);
|
|
|
|
DrawText(hdc, szText, -1, (LPRECT) lprc, dt);
|
|
|
|
if (style & WS_DISABLED)
|
|
cv = SetTextColor(hdc, cv);
|
|
}
|
|
|
|
void StaticPaint(HWND hwnd, HDC hdc)
|
|
{
|
|
LONG style;
|
|
RC rc;
|
|
|
|
style = GetWindowLong(hwnd, GWL_STYLE);
|
|
if(!(style & WS_VISIBLE))
|
|
return;
|
|
|
|
GetClientRect(hwnd, (LPRECT) &rc);
|
|
switch(style & 0x0f)
|
|
{
|
|
case SS_BLACKRECT:
|
|
case SS_BLACKFRAME: // Inset rect
|
|
DrawRec3d(hdc, &rc, icvBtnShadow, icvBtnHilite, dr3All);
|
|
break;
|
|
case SS_GRAYRECT:
|
|
case SS_GRAYFRAME:
|
|
rc.xLeft++;
|
|
rc.yTop++;
|
|
DrawRec3d(hdc, &rc, icvBtnHilite, icvBtnHilite, dr3All);
|
|
OffsetRect((LPRECT) &rc, -1, -1);
|
|
DrawRec3d(hdc, &rc, icvBtnShadow, icvBtnShadow, dr3All);
|
|
break;
|
|
case SS_WHITERECT: // outset rect
|
|
case SS_WHITEFRAME:
|
|
DrawRec3d(hdc, &rc, icvBtnHilite, icvBtnShadow, dr3All);
|
|
break;
|
|
case SS_LEFT:
|
|
case SS_CENTER:
|
|
case SS_RIGHT:
|
|
case SS_LEFTNOWORDWRAP:
|
|
{
|
|
HANDLE hfont;
|
|
HBRUSH hbr;
|
|
|
|
if((hfont = (HANDLE)SendMessage(hwnd, WM_GETFONT, 0, 0L)) != NULL)
|
|
hfont = SelectObject(hdc, hfont);
|
|
SetBkMode(hdc, OPAQUE);
|
|
|
|
if(( hbr = SEND_COLOR_STATIC_MESSAGE(GetParent(hwnd), hwnd, hdc)) != NULL)
|
|
hbr = (HBRUSH) SelectObject(hdc, hbr);
|
|
|
|
StaticPrint(hwnd, hdc, (RC FAR *)&rc, style);
|
|
|
|
if (hfont != NULL)
|
|
SelectObject(hdc, hfont);
|
|
|
|
if (hbr != NULL)
|
|
SelectObject(hdc, hbr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT EXPORT_FUNC StaticWndProc3d(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
|
|
switch (wm)
|
|
{
|
|
case WM_NCDESTROY:
|
|
return CleanupSubclass(hwnd, wm, wParam, lParam, ctStatic);
|
|
|
|
case WM_PAINT:
|
|
if ((hdc = (HDC) wParam) == NULL)
|
|
{
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
ClipCtlDc(hwnd, hdc);
|
|
}
|
|
StaticPaint(hwnd, hdc);
|
|
if (wParam == (WPARAM)NULL)
|
|
EndPaint(hwnd, &ps);
|
|
return 0L;
|
|
|
|
case WM_ENABLE:
|
|
hdc = GetDC(hwnd);
|
|
ClipCtlDc(hwnd, hdc);
|
|
StaticPaint(hwnd, hdc);
|
|
ReleaseDC(hwnd, hdc);
|
|
return 0L;
|
|
}
|
|
return CallWindowProc((WNDPROC) LpfnGetDefWndProc(hwnd, ctStatic), hwnd, wm, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
| LibMain
|
|
-----------------------------------------------------------------------*/
|
|
|
|
BOOL LibMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
UINT wT;
|
|
DWORD dwVersion;
|
|
|
|
switch(dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
g3d.hmodLib = (HINSTANCE) hModule;
|
|
g3d.hinstLib = (HINSTANCE) g3d.hmodLib;
|
|
|
|
dwVersion = (DWORD)GetVersion();
|
|
|
|
wT = LOWORD(GetVersion());
|
|
|
|
if (dwVersion & 0x80000000)
|
|
g3d.verWindows = 0x0300 | HIBYTE(wT);
|
|
else
|
|
g3d.verWindows = (LOBYTE(wT) << 8) | HIBYTE(wT);
|
|
|
|
g3d.dxFrame = GetSystemMetrics(SM_CXDLGFRAME)-dxBorder;
|
|
g3d.dyFrame = GetSystemMetrics(SM_CYDLGFRAME)-dyBorder;
|
|
g3d.dyCaption = GetSystemMetrics(SM_CYCAPTION);
|
|
g3d.dxSysMenu = GetSystemMetrics(SM_CXSIZE);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// LoadUIBitmap() - load a bitmap resource
|
|
//
|
|
// load a bitmap resource from a resource file, converting all
|
|
// the standard UI colors to the current user specifed ones.
|
|
//
|
|
// this code is designed to load bitmaps used in "gray ui" or
|
|
// "toolbar" code.
|
|
//
|
|
// the bitmap must be a 4bpp windows 3.0 DIB, with the standard
|
|
// VGA 16 colors.
|
|
//
|
|
// the bitmap must be authored with the following colors
|
|
//
|
|
// Window Text Black (index 0)
|
|
// Button Shadow gray (index 7)
|
|
// Button Face lt gray (index 8)
|
|
// Button Highlight white (index 15)
|
|
// Window Color yellow (index 11)
|
|
// Window Frame green (index 10)
|
|
//
|
|
// Example:
|
|
//
|
|
// hbm = LoadUIBitmap(hInstance, "TestBmp",
|
|
// GetSysColor(COLOR_WINDOWTEXT),
|
|
// GetSysColor(COLOR_BTNFACE),
|
|
// GetSysColor(COLOR_BTNSHADOW),
|
|
// GetSysColor(COLOR_BTNHIGHLIGHT),
|
|
// GetSysColor(COLOR_WINDOW),
|
|
// GetSysColor(COLOR_WINDOWFRAME));
|
|
//
|
|
// Author: JimBov, ToddLa
|
|
//
|
|
//
|
|
|
|
static HBITMAP STDCALL LoadUIBitmap(
|
|
HINSTANCE hInstance, // EXE file to load resource from
|
|
LPCSTR szName, // name of bitmap resource
|
|
COLORREF rgbText, // color to use for "Button Text"
|
|
COLORREF rgbFace, // color to use for "Button Face"
|
|
COLORREF rgbShadow, // color to use for "Button Shadow"
|
|
COLORREF rgbHighlight, // color to use for "Button Hilight"
|
|
COLORREF rgbWindow, // color to use for "Window Color"
|
|
COLORREF rgbFrame) // color to use for "Window Frame"
|
|
{
|
|
HBITMAP hbm;
|
|
HRSRC hrsrc;
|
|
HGLOBAL h;
|
|
HDC hdc;
|
|
DWORD size;
|
|
|
|
// Load the bitmap resource and make a writable copy.
|
|
|
|
hrsrc = FindResource(hInstance, szName, RT_BITMAP);
|
|
if (!hrsrc)
|
|
return(NULL);
|
|
size = SizeofResource(hInstance, hrsrc);
|
|
h = LoadResource(hInstance, hrsrc);
|
|
if (!h)
|
|
return(NULL);
|
|
|
|
LPBITMAPINFO lpbi = (LPBITMAPINFO) GlobalAlloc(GPTR, size);
|
|
|
|
if (!lpbi)
|
|
return(NULL);
|
|
|
|
CopyMemory(lpbi, h, size);
|
|
|
|
*(LPCOLORREF) &lpbi->bmiColors[0] = (rgbText); // Black
|
|
*(LPCOLORREF) &lpbi->bmiColors[7] = (rgbShadow); // gray
|
|
*(LPCOLORREF) &lpbi->bmiColors[8] = (rgbFace); // lt gray
|
|
*(LPCOLORREF) &lpbi->bmiColors[15] = (rgbHighlight); // white
|
|
*(LPCOLORREF) &lpbi->bmiColors[11] = (rgbWindow); // yellow
|
|
*(LPCOLORREF) &lpbi->bmiColors[10] = (rgbFrame); // green
|
|
|
|
hdc = GetDC(NULL);
|
|
|
|
hbm = CreateDIBitmap(hdc, &lpbi->bmiHeader, CBM_INIT, (LPBYTE) (&lpbi->bmiColors[ 16 ]),
|
|
lpbi, DIB_RGB_COLORS);
|
|
|
|
ReleaseDC(NULL, hdc);
|
|
GlobalFree(lpbi);
|
|
|
|
return(hbm);
|
|
}
|