1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helppopupwindow.cxx,v $
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 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
39 #include "helppopupwindow.hxx"
40 #include <osl/diagnose.h>
42 //------------------------------------------------------------------------
44 //------------------------------------------------------------------------
49 //------------------------------------------------------------------------
51 //------------------------------------------------------------------------
53 namespace /* private */
56 const LPTSTR CURRENT_INSTANCE
= TEXT("CurrInst");
60 //------------------------------------------------------------------------
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(
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(
155 HELPPOPUPWND_CLASS_NAME
,
167 OSL_ENSURE( m_hwnd
, "creating help popup window failed" );
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
;
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
;
216 reinterpret_cast<LPCTSTR
>(m_HelpText
.getStr( )),
217 m_HelpText
.getLength( ),
221 // add the necessary space for the frames
227 OUTER_FRAME_WIDTH
* 2 +
228 INNER_FRAME_WIDTH
* 2;
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
);
250 calcWindowRect( &rect
);
252 // adjust the window size
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
)
278 OSL_ASSERT( m_hwnd
);
280 HDC hdc
= GetDC( m_hwnd
);
282 // assuming these are screen coordinates
285 popX
= x
- ( popWidth
/ 2 );
288 int xScreen
= GetDeviceCaps( hdc
, HORZRES
);
289 int yScreen
= GetDeviceCaps( hdc
, VERTRES
);
297 if ((popX
+ popWidth
) > xScreen
)
298 popX
= xScreen
- popWidth
;
300 if ((popY
+ popHeight
) > yScreen
)
301 popY
= yScreen
- popHeight
;
310 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
);
312 ReleaseDC( m_hwnd
, hdc
);
315 //---------------------------------------------------
317 //---------------------------------------------------
319 void SAL_CALL
CHelpPopupWindow::onPaint( HWND hWnd
, HDC hdc
)
323 HGDIOBJ hpen
, hpenOld
;
326 COLORREF oldTextColor
;
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
);
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
);
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
;
392 (LPWSTR
)m_HelpText
.getStr( ),
393 m_HelpText
.getLength( ),
397 SelectObject( hdc
, oldFont
);
398 SetTextColor( hdc
, oldTextColor
);
399 SetBkColor( hdc
, oldBkColor
);
401 // set text color and text background color
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
);
415 rc
.left
+ SHADOW_OFFSET
,
416 rc
.bottom
- SHADOW_HEIGHT
,
417 rc
.right
- SHADOW_OFFSET
- SHADOW_WIDTH
,
424 rc
.right
- SHADOW_WIDTH
,
425 rc
.top
+ SHADOW_OFFSET
,
427 rc
.bottom
- SHADOW_OFFSET
,
430 SelectObject(hdc
, hbrOld
);
431 SetTextColor( hdc
, oldTextColor
);
432 SetBkColor( hdc
, oldBkColor
);
435 //---------------------------------------------------
437 //---------------------------------------------------
439 void SAL_CALL
CHelpPopupWindow::onNcDestroy()
444 //---------------------------------------------------
446 //---------------------------------------------------
448 void SAL_CALL
CHelpPopupWindow::onCreate( HWND hwnd
)
452 HDC hdc
= GetDC( m_hwnd
);
454 HGDIOBJ oldFont
= SelectObject(
455 hdc
, GetStockObject( DEFAULT_GUI_FONT
) );
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
)
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
507 CHelpPopupWindow
* pImpl
= reinterpret_cast< CHelpPopupWindow
* >(
508 GetProp( hWnd
, CURRENT_INSTANCE
) );
514 BeginPaint(hWnd
, &ps
);
515 pImpl
->onPaint( hWnd
, ps
.hdc
);
522 // RemoveProp returns the saved value on success
523 CHelpPopupWindow
* pImpl
= reinterpret_cast< CHelpPopupWindow
* >(
524 RemoveProp( hWnd
, CURRENT_INSTANCE
) );
528 pImpl
->onNcDestroy();
542 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
548 //---------------------------------------------------
550 //---------------------------------------------------
552 ATOM SAL_CALL
CHelpPopupWindow::RegisterWindowClass( )
554 osl::MutexGuard
aGuard( s_Mutex
);
556 if ( 0 == s_ClassAtom
)
558 // register the window class
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
++;
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" );