X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=lib%2Fuser32%2Fcontrols%2Fstatic.c;fp=lib%2Fuser32%2Fcontrols%2Fstatic.c;h=603517014303af1e6f594ca7ebda4c0e5a6256c2;hp=0000000000000000000000000000000000000000;hb=ee8b63255465d8c28be3e7bd11628015708fc1ab;hpb=c99688ef1ab339c8746ecc385bde679623084c71 diff --git a/lib/user32/controls/static.c b/lib/user32/controls/static.c new file mode 100644 index 0000000..6035170 --- /dev/null +++ b/lib/user32/controls/static.c @@ -0,0 +1,565 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS User32 + * PURPOSE: Static control + * FILE: lib/user32/controls/static.c + * PROGRAMER: Ge van Geldorp (ge@gse.nl) + * REVISION HISTORY: 2003/05/28 GvG Created + * NOTES: Adapted from Wine + */ + +#include "windows.h" +#include "user32/regcontrol.h" + +static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style ); +static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ); +static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style ); +static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style ); +static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style ); +static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style ); +//static LRESULT CALLBACK StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); +static LRESULT CALLBACK StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +static COLORREF color_black, color_gray, color_white; + +/* offsets for GetWindowLong for static private information */ +#define HFONT_GWL_OFFSET 0 +#define HICON_GWL_OFFSET (sizeof(HFONT)) +#define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON)) + +typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style ); + +static pfPaint staticPaintFunc[SS_TYPEMASK+1] = +{ + STATIC_PaintTextfn, /* SS_LEFT */ + STATIC_PaintTextfn, /* SS_CENTER */ + STATIC_PaintTextfn, /* SS_RIGHT */ + STATIC_PaintIconfn, /* SS_ICON */ + STATIC_PaintRectfn, /* SS_BLACKRECT */ + STATIC_PaintRectfn, /* SS_GRAYRECT */ + STATIC_PaintRectfn, /* SS_WHITERECT */ + STATIC_PaintRectfn, /* SS_BLACKFRAME */ + STATIC_PaintRectfn, /* SS_GRAYFRAME */ + STATIC_PaintRectfn, /* SS_WHITEFRAME */ + NULL, /* SS_USERITEM */ + STATIC_PaintTextfn, /* SS_SIMPLE */ + STATIC_PaintTextfn, /* SS_LEFTNOWORDWRAP */ + STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */ + STATIC_PaintBitmapfn, /* SS_BITMAP */ + NULL, /* SS_ENHMETAFILE */ + STATIC_PaintEtchedfn, /* SS_ETCHEDHORIZ */ + STATIC_PaintEtchedfn, /* SS_ETCHEDVERT */ + STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */ +}; + + +/********************************************************************* + * static class descriptor + */ +const struct builtin_class_descr STATIC_builtin_class = +{ + L"Static", /* name */ + CS_GLOBALCLASS | CS_DBLCLKS, /* style */ + (WNDPROC) StaticWndProcW, /* procW */ + STATIC_EXTRA_BYTES, /* extra */ + (LPCWSTR) IDC_ARROW, /* cursor */ /* FIXME Wine uses IDC_ARROWA */ + 0 /* brush */ +}; + + +/*********************************************************************** + * STATIC_SetIcon + * + * Set the icon for an SS_ICON control. + */ +static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) +{ +#if 0 /* FIXME */ + HICON prevIcon; + CURSORICONINFO *info = hicon?(CURSORICONINFO *) GlobalLock16(HICON_16(hicon)):NULL; + + if ((style & SS_TYPEMASK) != SS_ICON) return 0; + if (hicon && !info) { + ERR("huh? hicon!=0, but info=0???\n"); + return 0; + } + prevIcon = (HICON)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hicon ); + if (hicon) + { + SetWindowPos( hwnd, 0, 0, 0, info->nWidth, info->nHeight, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); + GlobalUnlock16(HICON_16(hicon)); + } + return prevIcon; +#else + OutputDebugStringA("STATIC_SetIcon not implemented\n"); + return NULL; +#endif +} + +/*********************************************************************** + * STATIC_SetBitmap + * + * Set the bitmap for an SS_BITMAP control. + */ +static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) +{ + HBITMAP hOldBitmap; + + if ((style & SS_TYPEMASK) != SS_BITMAP) return 0; + if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) { + OutputDebugStringA("huh? hBitmap!=0, but not bitmap\n"); + return 0; + } + hOldBitmap = (HBITMAP)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hBitmap ); + if (hBitmap) + { + BITMAP bm; + GetObjectW(hBitmap, sizeof(bm), &bm); + SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); + } + return hOldBitmap; +} + +/*********************************************************************** + * STATIC_LoadIconW + * + * Load the icon for an SS_ICON control. + */ +static HICON STATIC_LoadIconW( HWND hwnd, LPCWSTR name ) +{ + HINSTANCE hInstance = (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ); + HICON hicon = LoadIconW( hInstance, name ); + if (!hicon) hicon = LoadIconW( 0, name ); + return hicon; +} + +/*********************************************************************** + * STATIC_LoadBitmapW + * + * Load the bitmap for an SS_BITMAP control. + */ +static HBITMAP STATIC_LoadBitmapW( HWND hwnd, LPCWSTR name ) +{ + HINSTANCE hInstance = (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ); + HBITMAP hbitmap = LoadBitmapW( hInstance, name ); + if (!hbitmap) /* Try OEM icon (FIXME: is this right?) */ + hbitmap = LoadBitmapW( 0, name ); + return hbitmap; +} + +/*********************************************************************** + * STATIC_TryPaintFcn + * + * Try to immediately paint the control. + */ +static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style) +{ + LONG style = full_style & SS_TYPEMASK; + RECT rc; + + GetClientRect( hwnd, &rc ); + if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style]) + { + HDC hdc; + hdc = GetDC( hwnd ); + (staticPaintFunc[style])( hwnd, hdc, full_style ); + ReleaseDC( hwnd, hdc ); + } +} + +/*********************************************************************** + * StaticWndProcW + */ +static LRESULT CALLBACK StaticWndProcW( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LRESULT lResult = 0; + LONG full_style = GetWindowLongA( hwnd, GWL_STYLE ); + LONG style = full_style & SS_TYPEMASK; + + if (!IsWindow( hwnd )) return 0; + switch (uMsg) + { + case WM_CREATE: + if (style < 0L || style > SS_TYPEMASK) + { + OutputDebugStringA("Unknown style\n"); + return -1; + } + /* initialise colours */ + color_black = GetSysColor(COLOR_3DDKSHADOW); + color_gray = GetSysColor(COLOR_3DSHADOW); + color_white = GetSysColor(COLOR_3DHILIGHT); + break; + + case WM_NCDESTROY: + if (style == SS_ICON) { +/* + * FIXME + * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) ); + * + * We don't want to do this yet because DestroyIcon32 is broken. If the icon + * had already been loaded by the application the last thing we want to do is + * GlobalFree16 the handle. + */ + break; + } + else return DefWindowProcW(hwnd, uMsg, wParam, lParam); + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + if (staticPaintFunc[style]) + (staticPaintFunc[style])( hwnd, ps.hdc, full_style ); + EndPaint(hwnd, &ps); + } + break; + + case WM_ENABLE: + InvalidateRect(hwnd, NULL, TRUE); + break; + + case WM_SYSCOLORCHANGE: + color_black = GetSysColor(COLOR_3DDKSHADOW); + color_gray = GetSysColor(COLOR_3DSHADOW); + color_white = GetSysColor(COLOR_3DHILIGHT); + InvalidateRect(hwnd, NULL, TRUE); + break; + + case WM_NCCREATE: + if (full_style & SS_SUNKEN) + SetWindowLongA( hwnd, GWL_EXSTYLE, + GetWindowLongA( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE ); + + lParam = (LPARAM)(((LPCREATESTRUCTW)lParam)->lpszName); + /* fall through */ + case WM_SETTEXT: + switch (style) { + case SS_ICON: + { + HICON hIcon; + hIcon = STATIC_LoadIconW(hwnd, (LPCWSTR)lParam); + /* FIXME : should we also return the previous hIcon here ??? */ + STATIC_SetIcon(hwnd, hIcon, style); + break; + } + case SS_BITMAP: + { + HBITMAP hBitmap; + hBitmap = STATIC_LoadBitmapW(hwnd, (LPCWSTR)lParam); + STATIC_SetBitmap(hwnd, hBitmap, style); + break; + } + case SS_LEFT: + case SS_CENTER: + case SS_RIGHT: + case SS_SIMPLE: + case SS_LEFTNOWORDWRAP: + { + if (HIWORD(lParam)) + { + lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam ); + } + if (uMsg == WM_SETTEXT) + STATIC_TryPaintFcn( hwnd, full_style ); + break; + } + default: + if (HIWORD(lParam)) + { + lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam ); + } + if(uMsg == WM_SETTEXT) + InvalidateRect(hwnd, NULL, TRUE); + } + return 1; /* success. FIXME: check text length */ + + case WM_SETFONT: + if ((style == SS_ICON) || (style == SS_BITMAP)) return 0; + SetWindowLongA( hwnd, HFONT_GWL_OFFSET, wParam ); + if (LOWORD(lParam)) + InvalidateRect( hwnd, NULL, TRUE ); + break; + + case WM_GETFONT: + return GetWindowLongA( hwnd, HFONT_GWL_OFFSET ); + + case WM_NCHITTEST: + if (full_style & SS_NOTIFY) + return HTCLIENT; + else + return HTTRANSPARENT; + + case WM_GETDLGCODE: + return DLGC_STATIC; + + case WM_LBUTTONDOWN: + if (! (full_style & SS_NOTIFY)) return 0; + SendMessageW(GetParent(hwnd), WM_COMMAND, + MAKEWPARAM((WORD) GetWindowLongW(hwnd, GWL_ID), STN_CLICKED), (LPARAM) hwnd); + return 0; + + case WM_LBUTTONDBLCLK: + if (! (full_style & SS_NOTIFY)) return 0; + SendMessageW(GetParent(hwnd), WM_COMMAND, + MAKEWPARAM((WORD) GetWindowLongW(hwnd, GWL_ID), STN_DBLCLK), (LPARAM) hwnd); + return 0; + + case STM_GETIMAGE: + case STM_GETICON: + return GetWindowLongA( hwnd, HICON_GWL_OFFSET ); + + case STM_SETIMAGE: + switch(wParam) { + case IMAGE_BITMAP: + lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, style ); + break; + case IMAGE_ICON: + lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, style ); + break; + default: + OutputDebugStringA("STM_SETIMAGE: Unhandled type\n"); + break; + } + InvalidateRect( hwnd, NULL, TRUE ); + break; + + case STM_SETICON: + lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, style ); + InvalidateRect( hwnd, NULL, TRUE ); + break; + + default: + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + return lResult; +} + +static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style ) +{ + DRAWITEMSTRUCT dis; + LONG id = GetWindowLongA( hwnd, GWL_ID ); + + dis.CtlType = ODT_STATIC; + dis.CtlID = id; + dis.itemID = 0; + dis.itemAction = ODA_DRAWENTIRE; + dis.itemState = 0; + dis.hwndItem = hwnd; + dis.hDC = hdc; + dis.itemData = 0; + GetClientRect( hwnd, &dis.rcItem ); + + SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); + SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); +} + +static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) +{ + RECT rc; + HBRUSH hBrush; + HFONT hFont; + UINT wFormat; + INT len; + WCHAR *text; + HPEN ShadowPen, HighlightPen; + + GetClientRect( hwnd, &rc); + + switch (style & SS_TYPEMASK) + { + case SS_LEFT: + wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP; + break; + + case SS_CENTER: + wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP; + break; + + case SS_RIGHT: + wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP; + break; + + case SS_SIMPLE: + wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP; + break; + + case SS_LEFTNOWORDWRAP: + wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER; + break; + + default: + return; + } + + if (style & SS_NOPREFIX) + wFormat |= DT_NOPREFIX; + switch(style & SS_ELLIPSISMASK) + { + case SS_WORDELLIPSIS: + wFormat |= DT_WORD_ELLIPSIS | DT_SINGLELINE; + break; + case SS_ENDELLIPSIS: + wFormat |= DT_END_ELLIPSIS; + wFormat &= ~DT_WORDBREAK; + break; + case SS_PATHELLIPSIS: + wFormat |= DT_PATH_ELLIPSIS; + wFormat &= ~DT_WORDBREAK; + break; + } + + if ((hFont = (HFONT)GetWindowLongA( hwnd, HFONT_GWL_OFFSET ))) SelectObject( hdc, hFont ); + + if ((style & SS_NOPREFIX) || ((style & SS_TYPEMASK) != SS_SIMPLE)) + { + hBrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, + (WPARAM)hdc, (LPARAM)hwnd ); + if (!hBrush) /* did the app forget to call defwindowproc ? */ + hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC, + (WPARAM)hdc, (LPARAM)hwnd); + FillRect( hdc, &rc, hBrush ); + } + if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + SetBkMode(hdc, TRANSPARENT); + + if (style & SS_SUNKEN) + { + ShadowPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW)); + SelectObject(hdc, ShadowPen); + MoveToEx(hdc, 0, rc.bottom - 2, NULL); + LineTo(hdc, 0, 0); + LineTo(hdc, rc.right - 1, 0); + HighlightPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); + SelectObject(hdc, HighlightPen); + LineTo(hdc, rc.right - 1, rc.bottom - 1); + LineTo(hdc, -1, rc.bottom - 1); + SelectObject(hdc, GetStockObject(WHITE_PEN)); + DeleteObject(HighlightPen); + DeleteObject(ShadowPen); + rc.left++; + rc.right--; + rc.top++; + rc.bottom--; + } + + if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return; + if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return; + SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text ); + DrawTextW( hdc, text, -1, &rc, wFormat ); + HeapFree( GetProcessHeap(), 0, text ); +} + +static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style ) +{ + RECT rc; + HBRUSH hBrush; + + GetClientRect( hwnd, &rc); + + switch (style & SS_TYPEMASK) + { + case SS_BLACKRECT: + hBrush = CreateSolidBrush(color_black); + FillRect( hdc, &rc, hBrush ); + break; + case SS_GRAYRECT: + hBrush = CreateSolidBrush(color_gray); + FillRect( hdc, &rc, hBrush ); + break; + case SS_WHITERECT: + hBrush = CreateSolidBrush(color_white); + FillRect( hdc, &rc, hBrush ); + break; + case SS_BLACKFRAME: + hBrush = CreateSolidBrush(color_black); + FrameRect( hdc, &rc, hBrush ); + break; + case SS_GRAYFRAME: + hBrush = CreateSolidBrush(color_gray); + FrameRect( hdc, &rc, hBrush ); + break; + case SS_WHITEFRAME: + hBrush = CreateSolidBrush(color_white); + FrameRect( hdc, &rc, hBrush ); + break; + default: + return; + } + DeleteObject( hBrush ); +} + + +static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style ) +{ + RECT rc; + HBRUSH hbrush; + HICON hIcon; + + GetClientRect( hwnd, &rc ); + hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, + (WPARAM)hdc, (LPARAM)hwnd ); + FillRect( hdc, &rc, hbrush ); + if ((hIcon = (HICON)GetWindowLongA( hwnd, HICON_GWL_OFFSET ))) + DrawIcon( hdc, rc.left, rc.top, hIcon ); +} + +static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style ) +{ + RECT rc; + HBRUSH hbrush; + HDC hMemDC; + HBITMAP hBitmap, oldbitmap; + + GetClientRect( hwnd, &rc ); + hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, + (WPARAM)hdc, (LPARAM)hwnd ); + FillRect( hdc, &rc, hbrush ); + + if ((hBitmap = (HBITMAP)GetWindowLongA( hwnd, HICON_GWL_OFFSET ))) + { + BITMAP bm; + SIZE sz; + + if(GetObjectType(hBitmap) != OBJ_BITMAP) return; + if (!(hMemDC = CreateCompatibleDC( hdc ))) return; + GetObjectW(hBitmap, sizeof(bm), &bm); + GetBitmapDimensionEx(hBitmap, &sz); + oldbitmap = SelectObject(hMemDC, hBitmap); + BitBlt(hdc, sz.cx, sz.cy, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, + SRCCOPY); + SelectObject(hMemDC, oldbitmap); + DeleteDC(hMemDC); + } +} + + +static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style ) +{ + RECT rc; + + GetClientRect( hwnd, &rc ); + switch (style & SS_TYPEMASK) + { + case SS_ETCHEDHORZ: +#if 0 /* This is what seems logical */ + DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM); +#else /* But this is what NT, Win2k and WinXP actually do */ + DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP); +#endif + break; + case SS_ETCHEDVERT: +#if 0 /* This is what seems logical */ + DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT); +#else /* But this is what NT, Win2k and WinXP actually do */ + DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT); +#endif + break; + case SS_ETCHEDFRAME: + DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT); + break; + } +}