windows-nt/Source/XPSP1/NT/printscan/ui/uicommon/wiatextc.h
2020-09-26 16:20:57 +08:00

672 lines
19 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORPORATION, 1998
*
* TITLE: WIATEXTC.H
*
* VERSION: 1.0
*
* AUTHOR: ShaunIv
*
* DATE: 7/30/1999
*
* DESCRIPTION: Highlighted static control. Like a static, but acts like a
* hyperlink
*
*
* Use the following values in the dialog resource editor to put it in a dialog:
*
* Style:
* Hyperlink: 0x50010000 (WS_CHILD|WS_VISIBLE|WS_TABSTOP)
* IconStatic: 0x50010008 (WS_CHILD|WS_VISIBLE|0x00000008)
* Class: WiaTextControl
* ExStyle: 0x00000000
*
* Register before use using:
* CWiaTextControl::RegisterClass(g_hInstance);
*
*******************************************************************************/
#ifndef __WIATEXTC_H_INCLUDED
#define __WIATEXTC_H_INCLUDED
#include <windows.h>
#include <windowsx.h>
#include "simcrack.h"
#include "miscutil.h"
#define WIATEXT_STATIC_CLASSNAMEW L"WiaTextControl"
#define WIATEXT_STATIC_CLASSNAMEA "WiaTextControl"
#ifdef UNICODE
#define WIATEXT_STATIC_CLASSNAME WIATEXT_STATIC_CLASSNAMEW
#else
#define WIATEXT_STATIC_CLASSNAME WIATEXT_STATIC_CLASSNAMEA
#endif
// Styles
#define WTS_SINGLELINE 0x00000001 // Single line
#define WTS_PATHELLIPSIS 0x00000002 // Use to truncate string in the middle
#define WTS_ENDELLIPSIS 0x00000004 // Use to truncate string at the end
#define WTS_ICONSTATIC 0x00000008 // Static control with an icon
#define WTS_RIGHT 0x00000010 // Right aligned
// Undefined in VC6 SDK
#ifndef COLOR_HOTLIGHT
#define COLOR_HOTLIGHT 26
#endif
// Undefined in VC6 SDK
#ifndef IDC_HAND
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
#define DEFAULT_ICON_STATIC_BACKGROUND_COLOR GetSysColor(COLOR_3DFACE)
#define DEFAULT_ICON_STATIC_FOREGROUND_COLOR GetSysColor(COLOR_WINDOWTEXT)
#define WM_WIA_STATIC_SETICON (WM_USER+1)
class CWiaTextControl
{
private:
enum
{
StateNormal = 0,
StateHover = 1,
StateFocus = 2,
StateDisabled = 4
};
// Timer IDs
enum
{
IDT_MOUSEPOS = 1
};
enum
{
IconMargin = 0
};
private:
HWND m_hWnd;
COLORREF m_crColorNormal;
COLORREF m_crColorHover;
COLORREF m_crColorFocus;
COLORREF m_crColorDisabled;
COLORREF m_crForegroundColor;
RECT m_rcTextWidth;
HFONT m_hFont;
int m_CurrentState;
RECT m_rcHighlight;
HCURSOR m_hHandCursor;
HBITMAP m_hBitmap;
SIZE m_sizeWindow;
bool m_bIconStaticMode;
HBRUSH m_hBackgroundBrush;
HICON m_hIcon;
private:
CWiaTextControl(void);
CWiaTextControl( const CWiaTextControl & );
CWiaTextControl &operator=( const CWiaTextControl & );
private:
CWiaTextControl( HWND hWnd )
: m_hWnd(hWnd),
m_crColorNormal(GetSysColor(COLOR_HOTLIGHT)),
m_crColorHover(RGB(255,0,0)),
m_crColorFocus(GetSysColor(COLOR_HOTLIGHT)),
m_crColorDisabled(GetSysColor(COLOR_GRAYTEXT)),
m_crForegroundColor(DEFAULT_ICON_STATIC_FOREGROUND_COLOR),
m_hFont(NULL),
m_hHandCursor(NULL),
m_hBitmap(NULL),
m_hBackgroundBrush(NULL),
m_hIcon(NULL),
m_CurrentState(StateNormal),
m_bIconStaticMode(false)
{
CreateNewFont(reinterpret_cast<HFONT>(GetStockObject(SYSTEM_FONT)));
}
~CWiaTextControl(void)
{
m_hWnd = NULL;
if (m_hIcon)
{
DestroyIcon(m_hIcon);
m_hIcon = NULL;
}
if (m_hHandCursor)
{
m_hHandCursor = NULL;
}
if (m_hFont)
{
DeleteObject(m_hFont);
m_hFont = NULL;
}
if (m_hBitmap)
{
DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
if (m_hBackgroundBrush)
{
DeleteObject(m_hBackgroundBrush);
m_hBackgroundBrush = NULL;
}
}
COLORREF GetCurrentColor(void)
{
if (StateDisabled & m_CurrentState)
return m_crColorDisabled;
if (StateHover & m_CurrentState)
return m_crColorHover;
if (StateFocus & m_CurrentState)
return m_crColorFocus;
else return m_crColorNormal;
}
void CreateNewFont( HFONT hFont )
{
if (m_hFont)
{
DeleteObject(m_hFont);
m_hFont = NULL;
}
if (hFont)
{
LOGFONT lf;
if (GetObject( hFont, sizeof(LOGFONT), &lf ))
{
lf.lfUnderline = TRUE;
m_hFont = CreateFontIndirect( &lf );
}
}
}
private:
LRESULT OnEraseBkgnd( WPARAM wParam, LPARAM lParam )
{
RedrawBitmap(false);
return TRUE;
}
LRESULT OnSetIcon( WPARAM, LPARAM lParam )
{
if (m_hIcon)
{
DestroyIcon(m_hIcon);
m_hIcon = NULL;
}
m_hIcon = reinterpret_cast<HICON>(lParam);
RedrawBitmap(true);
return 0;
}
LRESULT OnSetFocus( WPARAM, LPARAM )
{
m_CurrentState |= StateFocus;
RedrawBitmap(true);
return 0;
}
LRESULT OnKillFocus( WPARAM, LPARAM )
{
m_CurrentState &= ~StateFocus;
RedrawBitmap(true);
return 0;
}
void DrawHyperlinkControl( HDC hDC )
{
RECT rcClient;
GetClientRect(m_hWnd,&rcClient);
// Make sure we start with a fresh rect
ZeroMemory( &m_rcHighlight, sizeof(m_rcHighlight) );
HBRUSH hbrBackground = NULL;
HWND hWndParent = GetParent(m_hWnd);
if (hWndParent)
hbrBackground = reinterpret_cast<HBRUSH>(SendMessage(hWndParent,WM_CTLCOLORSTATIC,reinterpret_cast<WPARAM>(hDC),reinterpret_cast<LPARAM>(m_hWnd)));
if (!hbrBackground)
hbrBackground = reinterpret_cast<HBRUSH>(GetSysColorBrush(COLOR_WINDOW));
FillRect( hDC, &rcClient, hbrBackground );
LRESULT nWindowTextLength = SendMessage(m_hWnd,WM_GETTEXTLENGTH,0,0);
LPTSTR pszWindowText = new TCHAR[nWindowTextLength+1];
if (pszWindowText)
{
if (SendMessage( m_hWnd, WM_GETTEXT, nWindowTextLength+1, reinterpret_cast<LPARAM>(pszWindowText) ) )
{
int nDrawTextFlags = DT_WORDBREAK|DT_TOP|DT_NOPREFIX;
INT_PTR nStyle = GetWindowLongPtr( m_hWnd, GWL_STYLE );
if (nStyle & WTS_SINGLELINE)
nDrawTextFlags |= DT_SINGLELINE;
if (nStyle & WTS_RIGHT)
nDrawTextFlags |= DT_RIGHT;
else nDrawTextFlags |= DT_LEFT;
if (nStyle & WTS_PATHELLIPSIS)
nDrawTextFlags |= DT_PATH_ELLIPSIS | DT_SINGLELINE;
if (nStyle & WTS_ENDELLIPSIS)
nDrawTextFlags |= DT_END_ELLIPSIS | DT_SINGLELINE;
m_rcHighlight = rcClient;
int nOldBkMode = SetBkMode( hDC, TRANSPARENT );
HFONT hOldFont = NULL;
if (m_hFont)
hOldFont = reinterpret_cast<HFONT>(SelectObject( hDC, m_hFont ));
COLORREF crOldColor = SetTextColor( hDC, GetCurrentColor() );
InflateRect(&m_rcHighlight,-1,-1);
DrawTextEx( hDC, pszWindowText, -1, &m_rcHighlight, nDrawTextFlags, NULL );
SetTextColor( hDC, crOldColor );
SetBkMode( hDC, nOldBkMode );
DrawTextEx( hDC, pszWindowText, -1, &m_rcHighlight, DT_CALCRECT|nDrawTextFlags , NULL );
InflateRect(&m_rcHighlight,1,1);
if (nStyle & WTS_RIGHT)
{
m_rcHighlight.left = rcClient.right - WiaUiUtil::Min<int>(rcClient.right,m_rcHighlight.right);
m_rcHighlight.right = rcClient.right;
m_rcHighlight.bottom = WiaUiUtil::Min<int>(rcClient.bottom,m_rcHighlight.bottom);
}
else
{
m_rcHighlight.right = WiaUiUtil::Min<int>(rcClient.right,m_rcHighlight.right);
m_rcHighlight.bottom = WiaUiUtil::Min<int>(rcClient.bottom,m_rcHighlight.bottom);
}
if (m_CurrentState & StateFocus)
DrawFocusRect( hDC, &m_rcHighlight );
if (m_hFont)
SelectObject( hDC, hOldFont );
}
delete[] pszWindowText;
}
}
void DrawIconStatic( HDC hDC )
{
RECT rcClient;
GetClientRect( m_hWnd, &rcClient );
FrameRect( hDC, &rcClient, GetSysColorBrush( COLOR_WINDOWFRAME ) );
InflateRect( &rcClient, -1, -1 );
FillRect( hDC, &rcClient, m_hBackgroundBrush );
InflateRect( &rcClient, -1, -1 );
CSimpleString str;
str.GetWindowText(m_hWnd);
if (str.Length())
{
int nDrawTextFlags = DT_WORDBREAK|DT_TOP|DT_LEFT|DT_NOPREFIX;
INT_PTR nStyle = GetWindowLongPtr( m_hWnd, GWL_STYLE );
if (nStyle & WTS_SINGLELINE)
nDrawTextFlags |= DT_SINGLELINE | DT_VCENTER;
if (nStyle & WTS_PATHELLIPSIS)
nDrawTextFlags |= DT_PATH_ELLIPSIS | DT_SINGLELINE;
if (nStyle & WTS_ENDELLIPSIS)
nDrawTextFlags |= DT_END_ELLIPSIS | DT_SINGLELINE;
if (m_hIcon)
{
int nIconMargin;
// Center the icon vertically
if (nStyle & WTS_SINGLELINE)
{
nIconMargin = (WiaUiUtil::RectHeight(rcClient) - GetSystemMetrics(SM_CYSMICON)) / 2;
}
else
{
nIconMargin = IconMargin;
}
DrawIconEx( hDC, rcClient.left+nIconMargin, rcClient.top+nIconMargin, m_hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL );
rcClient.left += rcClient.left + GetSystemMetrics(SM_CXSMICON) + nIconMargin*2;
}
int nOldBkMode = SetBkMode( hDC, TRANSPARENT );
HFONT hOldFont = NULL, hFont = (HFONT)SendMessage( m_hWnd, WM_GETFONT, 0, 0 );
if (!hFont)
hFont = (HFONT)SendMessage( GetParent(m_hWnd), WM_GETFONT, 0, 0 );
if (hFont)
hOldFont = SelectFont( hDC, hFont );
COLORREF crOldColor = SetTextColor( hDC, m_crForegroundColor );
DrawTextEx( hDC, const_cast<LPTSTR>(str.String()), str.Length(), &rcClient, nDrawTextFlags, NULL );
SetTextColor( hDC, crOldColor );
if (hOldFont)
SelectFont( hDC, hOldFont );
SetBkMode( hDC, nOldBkMode );
}
}
void RedrawBitmap( bool bRedraw )
{
if (m_hBitmap)
{
HDC hDC = GetDC(m_hWnd);
if (hDC)
{
HDC hMemDC = CreateCompatibleDC(hDC);
if (hMemDC)
{
HBITMAP hOldBitmap = SelectBitmap( hMemDC, m_hBitmap );
if (!m_bIconStaticMode)
DrawHyperlinkControl( hMemDC );
else DrawIconStatic( hMemDC );
SelectBitmap( hMemDC, hOldBitmap );
DeleteDC(hMemDC);
}
ReleaseDC(m_hWnd, hDC);
}
}
if (bRedraw)
{
InvalidateRect( m_hWnd, NULL, FALSE );
UpdateWindow( m_hWnd );
}
}
void CheckMousePos(void)
{
POINT pt;
GetCursorPos(&pt);
MapWindowPoints( NULL, m_hWnd, &pt, 1 );
if (PtInRect( &m_rcHighlight, pt ))
{
if ((m_CurrentState & StateHover)==0)
{
m_CurrentState |= StateHover;
RedrawBitmap(true);
}
}
else
{
if (m_CurrentState & StateHover)
{
m_CurrentState &= ~StateHover;
RedrawBitmap(true);
}
}
}
LRESULT OnTimer( WPARAM wParam, LPARAM lParam )
{
if (wParam == IDT_MOUSEPOS)
{
CheckMousePos();
return 0;
}
return DefWindowProc( m_hWnd, WM_TIMER, wParam, lParam );
}
LRESULT OnMove( WPARAM wParam, LPARAM lParam )
{
CheckMousePos();
return 0;
}
LRESULT OnSize( WPARAM wParam, LPARAM lParam )
{
if (SIZE_RESTORED == wParam || SIZE_MAXIMIZED == wParam)
{
if (m_hBitmap)
{
DeleteBitmap(m_hBitmap);
m_hBitmap = NULL;
}
HDC hDC = GetDC(m_hWnd);
if (hDC)
{
m_sizeWindow.cx = LOWORD(lParam);
m_sizeWindow.cy = HIWORD(lParam);
m_hBitmap = CreateCompatibleBitmap( hDC, LOWORD(lParam), HIWORD(lParam) );
ReleaseDC(m_hWnd,hDC);
}
}
RedrawBitmap(true);
CheckMousePos();
return 0;
}
LRESULT OnCreate( WPARAM, LPARAM )
{
if (!IsWindowEnabled(m_hWnd))
m_CurrentState |= StateDisabled;
INT_PTR nStyle = GetWindowLongPtr( m_hWnd, GWL_STYLE );
if (nStyle & WTS_ICONSTATIC)
m_bIconStaticMode = true;
SetTimer( m_hWnd, IDT_MOUSEPOS, 56, NULL );
m_hHandCursor = LoadCursor( NULL, IDC_HAND );
m_hBackgroundBrush = CreateSolidBrush(DEFAULT_ICON_STATIC_BACKGROUND_COLOR);
return 0;
}
LRESULT OnSetFont( WPARAM wParam, LPARAM lParam )
{
LRESULT lRes = DefWindowProc( m_hWnd, WM_SETFONT, wParam, lParam );
CreateNewFont(reinterpret_cast<HFONT>(wParam));
RedrawBitmap(LOWORD(lParam) != 0);
return lRes;
}
LRESULT OnSetText( WPARAM wParam, LPARAM lParam )
{
LRESULT lRes = DefWindowProc( m_hWnd, WM_SETTEXT, wParam, lParam );
RedrawBitmap(true);
return lRes;
}
LRESULT OnGetDlgCode( WPARAM, LPARAM )
{
if (!m_bIconStaticMode)
return DLGC_BUTTON;
return DLGC_STATIC;
}
void FireNotification( int nCode )
{
HWND hwndParent = GetParent(m_hWnd);
if (hwndParent)
{
SendNotifyMessage( hwndParent, WM_COMMAND, MAKEWPARAM(GetWindowLongPtr(m_hWnd,GWLP_ID),nCode), reinterpret_cast<LPARAM>(m_hWnd) );
}
}
LRESULT OnKeyDown( WPARAM wParam, LPARAM lParam )
{
if (!m_bIconStaticMode)
{
if (wParam == VK_SPACE)
FireNotification(BN_CLICKED);
else if (wParam == VK_RETURN)
FireNotification(BN_CLICKED);
}
return 0;
}
LRESULT OnNcHitTest( WPARAM, LPARAM lParam )
{
if (!m_bIconStaticMode)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
MapWindowPoints( NULL, m_hWnd, &pt, 1 );
if (PtInRect( &m_rcHighlight, pt ))
{
return HTCLIENT;
}
}
return HTTRANSPARENT;
}
LRESULT OnEnable( WPARAM wParam, LPARAM lParam )
{
if (wParam)
{
m_CurrentState &= ~StateDisabled;
}
else
{
m_CurrentState |= StateDisabled;
}
RedrawBitmap(true);
return 0;
}
LRESULT OnLButtonDown( WPARAM wParam, LPARAM lParam )
{
if (!m_bIconStaticMode)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (PtInRect(&m_rcHighlight,pt))
{
SetFocus(m_hWnd);
SetCapture(m_hWnd);
}
}
return 0;
}
LRESULT OnLButtonUp( WPARAM wParam, LPARAM lParam )
{
if (!m_bIconStaticMode)
{
if (GetCapture() == m_hWnd)
{
ReleaseCapture();
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (PtInRect(&m_rcHighlight,pt))
{
FireNotification(BN_CLICKED);
}
}
}
return 0;
}
LRESULT OnSetCursor( WPARAM wParam, LPARAM lParam )
{
if (!m_bIconStaticMode)
{
POINT pt;
GetCursorPos(&pt);
MapWindowPoints( NULL, m_hWnd, &pt, 1 );
if (PtInRect( &m_rcHighlight, pt ))
{
SetCursor( m_hHandCursor );
return 0;
}
}
return DefWindowProc( m_hWnd, WM_SETCURSOR, wParam, lParam );
}
LRESULT OnStyleChanged( WPARAM wParam, LPARAM lParam )
{
RedrawBitmap(true);
return 0;
}
LRESULT OnSysColorChange( WPARAM wParam, LPARAM lParam )
{
m_crColorNormal = GetSysColor(COLOR_HOTLIGHT);
m_crColorHover = RGB(255,0,0);
m_crColorFocus = GetSysColor(COLOR_HOTLIGHT);
m_crColorDisabled = GetSysColor(COLOR_GRAYTEXT);
RedrawBitmap(true);
return 0;
}
LRESULT OnPaint( WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint( m_hWnd, &ps );
if (hDC)
{
if (ps.fErase)
{
RedrawBitmap(false);
}
if (m_hBitmap)
{
HDC hMemDC = CreateCompatibleDC(hDC);
if (hMemDC)
{
HBITMAP hOldBitmap = SelectBitmap(hMemDC,m_hBitmap);
BitBlt( hDC, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top, hMemDC, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY );
SelectBitmap(hMemDC,hOldBitmap);
DeleteDC(hMemDC);
}
}
EndPaint( m_hWnd, &ps );
}
return 0;
}
public:
static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
SC_BEGIN_MESSAGE_HANDLERS(CWiaTextControl)
{
SC_HANDLE_MESSAGE( WM_CREATE, OnCreate );
SC_HANDLE_MESSAGE( WM_SETFONT, OnSetFont );
SC_HANDLE_MESSAGE( WM_PAINT, OnPaint );
SC_HANDLE_MESSAGE( WM_SETFOCUS, OnSetFocus );
SC_HANDLE_MESSAGE( WM_KILLFOCUS, OnKillFocus );
SC_HANDLE_MESSAGE( WM_SETTEXT, OnSetText );
SC_HANDLE_MESSAGE( WM_GETDLGCODE, OnGetDlgCode );
SC_HANDLE_MESSAGE( WM_ERASEBKGND, OnEraseBkgnd );
SC_HANDLE_MESSAGE( WM_TIMER, OnTimer );
SC_HANDLE_MESSAGE( WM_SIZE, OnSize );
SC_HANDLE_MESSAGE( WM_MOVE, OnMove );
SC_HANDLE_MESSAGE( WM_KEYDOWN, OnKeyDown );
SC_HANDLE_MESSAGE( WM_LBUTTONDOWN, OnLButtonDown );
SC_HANDLE_MESSAGE( WM_LBUTTONUP, OnLButtonUp );
SC_HANDLE_MESSAGE( WM_SETCURSOR, OnSetCursor );
SC_HANDLE_MESSAGE( WM_ENABLE, OnEnable );
SC_HANDLE_MESSAGE( WM_NCHITTEST, OnNcHitTest );
SC_HANDLE_MESSAGE( WM_STYLECHANGED, OnStyleChanged );
SC_HANDLE_MESSAGE( WM_SYSCOLORCHANGE, OnSysColorChange );
SC_HANDLE_MESSAGE( WM_WIA_STATIC_SETICON, OnSetIcon );
}
SC_END_MESSAGE_HANDLERS();
}
static BOOL RegisterClass( HINSTANCE hInstance )
{
WNDCLASSEX wcex;
ZeroMemory(&wcex,sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.lpszClassName = WIATEXT_STATIC_CLASSNAME;
return ::RegisterClassEx( &wcex );
}
};
#endif //__WIATEXTC_H_INCLUDED