merge the formfield patch from ooo-build
[ooovba.git] / fpicker / source / win32 / filepicker / helppopupwindow.cxx
blob1e1c2d6bfe64e074504d7a0dffbfd0f5b1dbb447
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helppopupwindow.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_fpicker.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
38 #include <tchar.h>
39 #include "helppopupwindow.hxx"
40 #include <osl/diagnose.h>
42 //------------------------------------------------------------------------
44 //------------------------------------------------------------------------
46 using rtl::OUString;
47 using osl::Mutex;
49 //------------------------------------------------------------------------
51 //------------------------------------------------------------------------
53 namespace /* private */
56 const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst");
60 //------------------------------------------------------------------------
61 // defines
62 //------------------------------------------------------------------------
64 #define HELPPOPUPWND_CLASS_NAME TEXT("hlppopupwnd###")
66 const sal_Int32 MAX_CHARS_PER_LINE = 55;
68 const sal_Int32 SHADOW_WIDTH = 6;
69 const sal_Int32 SHADOW_HEIGHT = 6;
70 const sal_Int32 SHADOW_OFFSET = 6;
71 const sal_Int32 YOFFSET = 20;
73 const DWORD OUTER_FRAME_COLOR = 0; // black
74 const sal_Int32 OUTER_FRAME_WIDTH = 1; // pixel
76 // it's the standard windows color of an inactive window border
77 const DWORD INNER_FRAME_COLOR = 0xC8D0D4;
78 const sal_Int32 INNER_FRAME_WIDTH = 1; // pixel
80 //---------------------------------------------------
81 // static member initialization
82 //---------------------------------------------------
84 osl::Mutex CHelpPopupWindow::s_Mutex;
85 ATOM CHelpPopupWindow::s_ClassAtom = 0;
86 sal_Int32 CHelpPopupWindow::s_RegisterWndClassCount = 0;
88 //---------------------------------------------------
90 //---------------------------------------------------
92 CHelpPopupWindow::CHelpPopupWindow(
93 HINSTANCE hInstance,
94 HWND hwndParent ) :
95 m_hMargins( 0 ),
96 m_vMargins( 0 ),
97 m_avCharWidth( 0 ),
98 m_avCharHeight( 0 ),
99 m_hwnd( NULL ),
100 m_hwndParent( hwndParent ),
101 m_hInstance( hInstance ),
102 m_hBitmapShadow( NULL ),
103 m_hBrushShadow( NULL )
105 m_bWndClassRegistered = RegisterWindowClass( ) ? sal_True : sal_False;
107 // create a pattern brush for the window shadow
108 WORD aPattern[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 };
110 m_hBitmapShadow = CreateBitmap( 8, 8, 1, 1, aPattern );
111 m_hBrushShadow = CreatePatternBrush( m_hBitmapShadow );
114 //---------------------------------------------------
116 //---------------------------------------------------
118 CHelpPopupWindow::~CHelpPopupWindow( )
120 // remember: we don't have to destroy the
121 // preview window because it will be destroyed
122 // by it's parent window (the FileOpen dialog)
123 // but we have to unregister the window class
124 if ( m_bWndClassRegistered )
125 UnregisterWindowClass( );
127 DeleteObject( m_hBitmapShadow );
128 DeleteObject( m_hBrushShadow );
131 //---------------------------------------------------
133 //---------------------------------------------------
135 void SAL_CALL CHelpPopupWindow::setText( const rtl::OUString& aHelpText )
137 m_HelpText = aHelpText;
140 //---------------------------------------------------
142 //---------------------------------------------------
144 void SAL_CALL CHelpPopupWindow::show( sal_Int32 x, sal_Int32 y )
146 OSL_ENSURE( NULL == m_hwnd, "method should not be called twice in sequence" );
148 // we create a window with length and heigth of 0
149 // first in order to get a device context of this
150 // window, then we calculate the upper left corner
151 // and the dimensions and resize the window
153 m_hwnd = CreateWindowEx(
154 NULL,
155 HELPPOPUPWND_CLASS_NAME,
156 NULL,
157 WS_POPUP,
162 m_hwndParent,
163 NULL,
164 m_hInstance,
165 (LPVOID)this );
167 OSL_ENSURE( m_hwnd, "creating help popup window failed" );
169 sal_Int32 cx_new;
170 sal_Int32 cy_new;
172 adjustWindowSize( &cx_new, &cy_new );
173 adjustWindowPos( x, y, cx_new, cy_new );
175 UpdateWindow( m_hwnd );
176 ShowWindow( m_hwnd, SW_SHOW );
179 //---------------------------------------------------
181 //---------------------------------------------------
183 HWND SAL_CALL CHelpPopupWindow::setParent( HWND hwndNewParent )
185 HWND oldParent = m_hwndParent;
187 m_hwndParent = hwndNewParent;
189 return oldParent;
192 //---------------------------------------------------
193 // calculates the necessary dimensions of the popup
194 // window including the margins etc.
195 //---------------------------------------------------
197 void SAL_CALL CHelpPopupWindow::calcWindowRect( LPRECT lprect )
199 OSL_ASSERT( m_hwnd && lprect );
201 SetRect( lprect, 0, 0, MAX_CHARS_PER_LINE * m_avCharWidth, 0 );
203 HDC hdc = GetDC( m_hwnd );
205 // set the font we are using later
206 HGDIOBJ oldFont = SelectObject(
207 hdc, GetStockObject( DEFAULT_GUI_FONT ) );
209 UINT nFormat = DT_WORDBREAK | DT_CALCRECT | DT_EXTERNALLEADING | DT_LEFT;
211 if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE )
212 nFormat |= DT_SINGLELINE;
214 DrawText(
215 hdc,
216 reinterpret_cast<LPCTSTR>(m_HelpText.getStr( )),
217 m_HelpText.getLength( ),
218 lprect,
219 nFormat );
221 // add the necessary space for the frames
222 // and margins
224 lprect->bottom +=
225 m_vMargins +
226 SHADOW_HEIGHT +
227 OUTER_FRAME_WIDTH * 2 +
228 INNER_FRAME_WIDTH * 2;
230 lprect->right +=
231 SHADOW_WIDTH +
232 2 * m_avCharWidth +
233 OUTER_FRAME_WIDTH * 2 +
234 INNER_FRAME_WIDTH * 2;
236 SelectObject( hdc, oldFont );
238 ReleaseDC( m_hwnd, hdc );
241 //---------------------------------------------------
243 //---------------------------------------------------
245 void SAL_CALL CHelpPopupWindow::adjustWindowSize( sal_Int32* cx_new, sal_Int32* cy_new )
247 OSL_ASSERT( cx_new && cy_new );
249 RECT rect;
250 calcWindowRect( &rect );
252 // adjust the window size
253 SetWindowPos(
254 m_hwnd,
255 NULL,
258 rect.right,
259 rect.bottom,
260 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
262 *cx_new = rect.right;
263 *cy_new = rect.bottom;
266 //---------------------------------------------------
268 //---------------------------------------------------
270 void SAL_CALL CHelpPopupWindow::adjustWindowPos(
271 sal_Int32 x, sal_Int32 y, sal_Int32 cx, sal_Int32 cy )
273 int popX;
274 int popY;
275 int popWidth;
276 int popHeight;
278 OSL_ASSERT( m_hwnd );
280 HDC hdc = GetDC( m_hwnd );
282 // assuming these are screen coordinates
283 popWidth = cx;
284 popHeight = cy;
285 popX = x - ( popWidth / 2 );
286 popY = y - YOFFSET;
288 int xScreen = GetDeviceCaps( hdc, HORZRES );
289 int yScreen = GetDeviceCaps( hdc, VERTRES );
291 if (popX < 0)
292 popX = 0;
294 if (popY < 0)
295 popY = 0;
297 if ((popX + popWidth) > xScreen)
298 popX = xScreen - popWidth;
300 if ((popY + popHeight) > yScreen)
301 popY = yScreen - popHeight;
303 SetWindowPos(
304 m_hwnd,
305 NULL,
306 popX,
307 popY,
310 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE );
312 ReleaseDC( m_hwnd, hdc );
315 //---------------------------------------------------
317 //---------------------------------------------------
319 void SAL_CALL CHelpPopupWindow::onPaint( HWND hWnd, HDC hdc )
321 RECT rc;
322 RECT rect;
323 HGDIOBJ hpen, hpenOld;
324 HGDIOBJ hbrOld;
325 COLORREF oldBkColor;
326 COLORREF oldTextColor;
327 HGDIOBJ oldFont;
328 HGDIOBJ oldBrush;
329 HGDIOBJ hBrush;
331 GetClientRect( hWnd, &rc );
333 // draw the black border
335 hBrush = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
336 oldBrush = SelectObject( hdc, hBrush );
338 hpen = CreatePen( PS_SOLID, 0, OUTER_FRAME_COLOR );
339 hpenOld = SelectObject( hdc, hpen );
341 Rectangle( hdc,
342 rc.left + OUTER_FRAME_WIDTH,
343 rc.top + OUTER_FRAME_WIDTH,
344 rc.right - SHADOW_WIDTH,
345 rc.bottom - SHADOW_HEIGHT);
347 SelectObject( hdc, oldBrush );
348 SelectObject( hdc, hpenOld );
350 DeleteObject( hBrush );
351 DeleteObject( hpen );
353 // draw a light gray border
355 hBrush = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
356 oldBrush = SelectObject( hdc, hBrush );
358 hpen = CreatePen( PS_SOLID, 0, INNER_FRAME_COLOR );
359 hpenOld = SelectObject( hdc, hpen );
361 Rectangle( hdc,
362 rc.left + OUTER_FRAME_WIDTH + 1,
363 rc.top + OUTER_FRAME_WIDTH + 1,
364 rc.right - SHADOW_WIDTH - OUTER_FRAME_WIDTH,
365 rc.bottom - SHADOW_HEIGHT - OUTER_FRAME_WIDTH );
367 SelectObject( hdc, oldBrush );
368 SelectObject( hdc, hpenOld );
370 DeleteObject( hBrush );
371 DeleteObject( hpen );
373 // Write some text to this window
375 rect.left = rc.left + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_hMargins;
376 rect.top = rc.top + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_vMargins / 2;
377 rect.right = rc.right - SHADOW_WIDTH - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_hMargins;
378 rect.bottom = rc.bottom - SHADOW_HEIGHT - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_vMargins / 2;
380 oldBkColor = SetBkColor( hdc, GetSysColor( COLOR_INFOBK ) );
381 oldTextColor = SetTextColor( hdc, COLOR_INFOTEXT );
383 oldFont = SelectObject( hdc, GetStockObject( DEFAULT_GUI_FONT ) );
385 UINT nFormat = DT_WORDBREAK | DT_EXTERNALLEADING | DT_LEFT;
387 if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE )
388 nFormat |= DT_SINGLELINE;
390 DrawText(
391 hdc,
392 (LPWSTR)m_HelpText.getStr( ),
393 m_HelpText.getLength( ),
394 &rect,
395 nFormat );
397 SelectObject( hdc, oldFont );
398 SetTextColor( hdc, oldTextColor );
399 SetBkColor( hdc, oldBkColor );
401 // set text color and text background color
402 // see MSDN PatBlt
404 oldBkColor = SetBkColor( hdc, RGB( 0, 0, 0 ) );
405 oldTextColor = SetTextColor( hdc, RGB( 255, 255, 255 ) );
407 // Get our brush for the shadow
409 UnrealizeObject( m_hBrushShadow );
410 hbrOld = SelectObject( hdc, m_hBrushShadow );
412 // bottom shadow
414 PatBlt(hdc,
415 rc.left + SHADOW_OFFSET,
416 rc.bottom - SHADOW_HEIGHT,
417 rc.right - SHADOW_OFFSET - SHADOW_WIDTH,
418 SHADOW_HEIGHT,
419 0xA000C9);
421 // right-side shadow
423 PatBlt(hdc,
424 rc.right - SHADOW_WIDTH,
425 rc.top + SHADOW_OFFSET,
426 SHADOW_WIDTH,
427 rc.bottom - SHADOW_OFFSET,
428 0xA000C9);
430 SelectObject(hdc, hbrOld);
431 SetTextColor( hdc, oldTextColor );
432 SetBkColor( hdc, oldBkColor );
435 //---------------------------------------------------
437 //---------------------------------------------------
439 void SAL_CALL CHelpPopupWindow::onNcDestroy()
441 m_hwnd = NULL;
444 //---------------------------------------------------
446 //---------------------------------------------------
448 void SAL_CALL CHelpPopupWindow::onCreate( HWND hwnd )
450 m_hwnd = hwnd;
452 HDC hdc = GetDC( m_hwnd );
454 HGDIOBJ oldFont = SelectObject(
455 hdc, GetStockObject( DEFAULT_GUI_FONT ) );
457 TEXTMETRIC tm;
458 GetTextMetrics( hdc, &tm );
460 m_avCharWidth = tm.tmAveCharWidth;
461 m_avCharHeight = tm.tmHeight;
463 if ( 0 == m_hMargins )
464 m_hMargins = m_avCharWidth;
466 if ( 0 == m_vMargins )
467 m_vMargins = m_avCharHeight;
469 SelectObject( hdc, oldFont );
471 ReleaseDC( m_hwnd, hdc );
474 //---------------------------------------------------
476 //---------------------------------------------------
478 LRESULT CALLBACK CHelpPopupWindow::WndProc(
479 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
481 LRESULT lResult = 0;
483 switch ( uMsg )
485 case WM_CREATE:
487 LPCREATESTRUCT lpcs =
488 reinterpret_cast< LPCREATESTRUCT >( lParam );
490 OSL_ASSERT( lpcs->lpCreateParams );
492 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
493 lpcs->lpCreateParams );
495 // connect the instance handle to the window
496 SetProp( hWnd, CURRENT_INSTANCE, pImpl );
498 pImpl->onCreate( hWnd );
500 // capture mouse and keybord events
501 SetCapture( hWnd );
503 break;
505 case WM_PAINT:
507 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
508 GetProp( hWnd, CURRENT_INSTANCE ) );
510 OSL_ASSERT( pImpl );
512 PAINTSTRUCT ps;
514 BeginPaint(hWnd, &ps);
515 pImpl->onPaint( hWnd, ps.hdc );
516 EndPaint(hWnd, &ps);
518 break;
520 case WM_NCDESTROY:
522 // RemoveProp returns the saved value on success
523 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
524 RemoveProp( hWnd, CURRENT_INSTANCE ) );
526 OSL_ASSERT( pImpl );
528 pImpl->onNcDestroy();
530 break;
532 case WM_LBUTTONDOWN:
533 case WM_KEYDOWN:
534 case WM_SYSKEYDOWN:
535 case WM_MBUTTONDOWN:
536 case WM_RBUTTONDOWN:
537 ReleaseCapture();
538 DestroyWindow(hWnd);
539 break;
541 default:
542 return DefWindowProc(hWnd, uMsg, wParam, lParam);
545 return lResult;
548 //---------------------------------------------------
550 //---------------------------------------------------
552 ATOM SAL_CALL CHelpPopupWindow::RegisterWindowClass( )
554 osl::MutexGuard aGuard( s_Mutex );
556 if ( 0 == s_ClassAtom )
558 // register the window class
559 WNDCLASSEX wndClsEx;
561 ZeroMemory(&wndClsEx, sizeof(wndClsEx));
563 wndClsEx.cbSize = sizeof(wndClsEx);
564 wndClsEx.lpfnWndProc = CHelpPopupWindow::WndProc;
565 wndClsEx.hInstance = m_hInstance;
566 wndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
567 wndClsEx.hbrBackground = (HBRUSH)GetStockObject( NULL_BRUSH );
568 wndClsEx.lpszClassName = HELPPOPUPWND_CLASS_NAME;
570 // register the preview window class
571 // !!! Win95 - the window class will be unregistered automaticly
572 // if the dll is unloaded
573 // Win2000 - the window class must be unregistered manually
574 // if the dll is unloaded
575 s_ClassAtom = RegisterClassEx( &wndClsEx );
576 OSL_ASSERT(s_ClassAtom);
579 // increment the register class counter
580 // so that we keep track of the number
581 // of class registrations
582 if (0 != s_ClassAtom)
583 s_RegisterWndClassCount++;
585 return s_ClassAtom;
588 //---------------------------------------------------
590 //---------------------------------------------------
592 void SAL_CALL CHelpPopupWindow::UnregisterWindowClass( )
594 osl::MutexGuard aGuard( s_Mutex );
596 OSL_ASSERT( ( (0 != s_ClassAtom) && (s_RegisterWndClassCount > 0)) ||
597 ( (0 == s_ClassAtom) && (0 == s_RegisterWndClassCount) ) );
599 // update the register class counter
600 // and unregister the window class if
601 // counter drops to zero
602 if ( 0 != s_ClassAtom )
604 s_RegisterWndClassCount--;
605 OSL_ASSERT( s_RegisterWndClassCount >= 0 );
608 if ( 0 == s_RegisterWndClassCount )
610 if ( !UnregisterClass(
611 (LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance ) )
613 OSL_ENSURE( false, "unregister window class failed" );
616 s_ClassAtom = 0;