1*b557fc96SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b557fc96SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b557fc96SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b557fc96SAndrew Rist  * distributed with this work for additional information
6*b557fc96SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b557fc96SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b557fc96SAndrew Rist  * "License"); you may not use this file except in compliance
9*b557fc96SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b557fc96SAndrew Rist  *
11*b557fc96SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b557fc96SAndrew Rist  *
13*b557fc96SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b557fc96SAndrew Rist  * software distributed under the License is distributed on an
15*b557fc96SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b557fc96SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b557fc96SAndrew Rist  * specific language governing permissions and limitations
18*b557fc96SAndrew Rist  * under the License.
19*b557fc96SAndrew Rist  *
20*b557fc96SAndrew Rist  *************************************************************/
21*b557fc96SAndrew Rist 
22*b557fc96SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_fpicker.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir //------------------------------------------------------------------------
28cdf0e10cSrcweir // includes
29cdf0e10cSrcweir //------------------------------------------------------------------------
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <tchar.h>
32cdf0e10cSrcweir #include "helppopupwindow.hxx"
33cdf0e10cSrcweir #include <osl/diagnose.h>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir //------------------------------------------------------------------------
36cdf0e10cSrcweir //
37cdf0e10cSrcweir //------------------------------------------------------------------------
38cdf0e10cSrcweir 
39cdf0e10cSrcweir using rtl::OUString;
40cdf0e10cSrcweir using osl::Mutex;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir //------------------------------------------------------------------------
43cdf0e10cSrcweir //
44cdf0e10cSrcweir //------------------------------------------------------------------------
45cdf0e10cSrcweir 
46cdf0e10cSrcweir namespace /* private */
47cdf0e10cSrcweir {
48cdf0e10cSrcweir 
49cdf0e10cSrcweir     const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst");
50cdf0e10cSrcweir 
51cdf0e10cSrcweir };
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //------------------------------------------------------------------------
54cdf0e10cSrcweir // defines
55cdf0e10cSrcweir //------------------------------------------------------------------------
56cdf0e10cSrcweir 
57cdf0e10cSrcweir #define HELPPOPUPWND_CLASS_NAME TEXT("hlppopupwnd###")
58cdf0e10cSrcweir 
59cdf0e10cSrcweir const sal_Int32 MAX_CHARS_PER_LINE = 55;
60cdf0e10cSrcweir 
61cdf0e10cSrcweir const sal_Int32 SHADOW_WIDTH  = 6;
62cdf0e10cSrcweir const sal_Int32 SHADOW_HEIGHT = 6;
63cdf0e10cSrcweir const sal_Int32 SHADOW_OFFSET = 6;
64cdf0e10cSrcweir const sal_Int32 YOFFSET       = 20;
65cdf0e10cSrcweir 
66cdf0e10cSrcweir const DWORD OUTER_FRAME_COLOR     = 0; // black
67cdf0e10cSrcweir const sal_Int32 OUTER_FRAME_WIDTH = 1; // pixel
68cdf0e10cSrcweir 
69cdf0e10cSrcweir // it's the standard windows color of an inactive window border
70cdf0e10cSrcweir const DWORD INNER_FRAME_COLOR     = 0xC8D0D4;
71cdf0e10cSrcweir const sal_Int32 INNER_FRAME_WIDTH = 1; // pixel
72cdf0e10cSrcweir 
73cdf0e10cSrcweir //---------------------------------------------------
74cdf0e10cSrcweir // static member initialization
75cdf0e10cSrcweir //---------------------------------------------------
76cdf0e10cSrcweir 
77cdf0e10cSrcweir osl::Mutex CHelpPopupWindow::s_Mutex;
78cdf0e10cSrcweir ATOM CHelpPopupWindow::s_ClassAtom = 0;
79cdf0e10cSrcweir sal_Int32 CHelpPopupWindow::s_RegisterWndClassCount = 0;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir //---------------------------------------------------
82cdf0e10cSrcweir //
83cdf0e10cSrcweir //---------------------------------------------------
84cdf0e10cSrcweir 
CHelpPopupWindow(HINSTANCE hInstance,HWND hwndParent)85cdf0e10cSrcweir CHelpPopupWindow::CHelpPopupWindow(
86cdf0e10cSrcweir 	HINSTANCE hInstance,
87cdf0e10cSrcweir     HWND hwndParent ) :
88cdf0e10cSrcweir     m_hMargins( 0 ),
89cdf0e10cSrcweir     m_vMargins( 0 ),
90cdf0e10cSrcweir     m_avCharWidth( 0 ),
91cdf0e10cSrcweir     m_avCharHeight( 0 ),
92cdf0e10cSrcweir     m_hwnd( NULL ),
93cdf0e10cSrcweir     m_hwndParent( hwndParent ),
94cdf0e10cSrcweir 	m_hInstance( hInstance ),
95cdf0e10cSrcweir     m_hBitmapShadow( NULL ),
96cdf0e10cSrcweir     m_hBrushShadow( NULL )
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     m_bWndClassRegistered = RegisterWindowClass( ) ? sal_True : sal_False;
99cdf0e10cSrcweir 
100cdf0e10cSrcweir     // create a pattern brush for the window shadow
101cdf0e10cSrcweir     WORD aPattern[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 };
102cdf0e10cSrcweir 
103cdf0e10cSrcweir     m_hBitmapShadow = CreateBitmap( 8, 8, 1, 1, aPattern );
104cdf0e10cSrcweir     m_hBrushShadow  = CreatePatternBrush( m_hBitmapShadow );
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
107cdf0e10cSrcweir //---------------------------------------------------
108cdf0e10cSrcweir //
109cdf0e10cSrcweir //---------------------------------------------------
110cdf0e10cSrcweir 
~CHelpPopupWindow()111cdf0e10cSrcweir CHelpPopupWindow::~CHelpPopupWindow( )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir     // remember: we don't have to destroy the
114cdf0e10cSrcweir     // preview window because it will be destroyed
115cdf0e10cSrcweir     // by it's parent window (the FileOpen dialog)
116cdf0e10cSrcweir     // but we have to unregister the window class
117cdf0e10cSrcweir     if ( m_bWndClassRegistered )
118cdf0e10cSrcweir         UnregisterWindowClass( );
119cdf0e10cSrcweir 
120cdf0e10cSrcweir     DeleteObject( m_hBitmapShadow );
121cdf0e10cSrcweir     DeleteObject( m_hBrushShadow );
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
124cdf0e10cSrcweir //---------------------------------------------------
125cdf0e10cSrcweir //
126cdf0e10cSrcweir //---------------------------------------------------
127cdf0e10cSrcweir 
setText(const rtl::OUString & aHelpText)128cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::setText( const rtl::OUString& aHelpText )
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     m_HelpText = aHelpText;
131cdf0e10cSrcweir }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir //---------------------------------------------------
134cdf0e10cSrcweir //
135cdf0e10cSrcweir //---------------------------------------------------
136cdf0e10cSrcweir 
show(sal_Int32 x,sal_Int32 y)137cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::show( sal_Int32 x, sal_Int32 y )
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     OSL_ENSURE( NULL == m_hwnd, "method should not be called twice in sequence" );
140cdf0e10cSrcweir 
141cdf0e10cSrcweir     // we create a window with length and heigth of 0
142cdf0e10cSrcweir     // first in order to get a device context of this
143cdf0e10cSrcweir     // window, then we calculate the upper left corner
144cdf0e10cSrcweir     // and the dimensions and resize the window
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     m_hwnd = CreateWindowEx(
147cdf0e10cSrcweir         NULL,
148cdf0e10cSrcweir         HELPPOPUPWND_CLASS_NAME,
149cdf0e10cSrcweir         NULL,
150cdf0e10cSrcweir         WS_POPUP,
151cdf0e10cSrcweir         0,
152cdf0e10cSrcweir         0,
153cdf0e10cSrcweir         0,
154cdf0e10cSrcweir         0,
155cdf0e10cSrcweir         m_hwndParent,
156cdf0e10cSrcweir         NULL,
157cdf0e10cSrcweir         m_hInstance,
158cdf0e10cSrcweir         (LPVOID)this );
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     OSL_ENSURE( m_hwnd, "creating help popup window failed" );
161cdf0e10cSrcweir 
162cdf0e10cSrcweir     sal_Int32 cx_new;
163cdf0e10cSrcweir     sal_Int32 cy_new;
164cdf0e10cSrcweir 
165cdf0e10cSrcweir     adjustWindowSize( &cx_new, &cy_new );
166cdf0e10cSrcweir     adjustWindowPos( x, y, cx_new, cy_new );
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     UpdateWindow( m_hwnd );
169cdf0e10cSrcweir     ShowWindow( m_hwnd, SW_SHOW );
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir //---------------------------------------------------
173cdf0e10cSrcweir //
174cdf0e10cSrcweir //---------------------------------------------------
175cdf0e10cSrcweir 
setParent(HWND hwndNewParent)176cdf0e10cSrcweir HWND SAL_CALL CHelpPopupWindow::setParent( HWND hwndNewParent )
177cdf0e10cSrcweir {
178cdf0e10cSrcweir     HWND oldParent = m_hwndParent;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     m_hwndParent = hwndNewParent;
181cdf0e10cSrcweir 
182cdf0e10cSrcweir     return oldParent;
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir //---------------------------------------------------
186cdf0e10cSrcweir // calculates the necessary dimensions of the popup
187cdf0e10cSrcweir // window including the margins etc.
188cdf0e10cSrcweir //---------------------------------------------------
189cdf0e10cSrcweir 
calcWindowRect(LPRECT lprect)190cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::calcWindowRect( LPRECT lprect )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir     OSL_ASSERT( m_hwnd && lprect );
193cdf0e10cSrcweir 
194cdf0e10cSrcweir     SetRect( lprect, 0, 0, MAX_CHARS_PER_LINE * m_avCharWidth, 0 );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir     HDC hdc = GetDC( m_hwnd );
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     // set the font we are using later
199cdf0e10cSrcweir     HGDIOBJ oldFont = SelectObject(
200cdf0e10cSrcweir         hdc, GetStockObject( DEFAULT_GUI_FONT ) );
201cdf0e10cSrcweir 
202cdf0e10cSrcweir     UINT nFormat = DT_WORDBREAK | DT_CALCRECT | DT_EXTERNALLEADING | DT_LEFT;
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE )
205cdf0e10cSrcweir         nFormat |= DT_SINGLELINE;
206cdf0e10cSrcweir 
207cdf0e10cSrcweir     DrawText(
208cdf0e10cSrcweir       hdc,
209cdf0e10cSrcweir       reinterpret_cast<LPCTSTR>(m_HelpText.getStr( )),
210cdf0e10cSrcweir       m_HelpText.getLength( ),
211cdf0e10cSrcweir       lprect,
212cdf0e10cSrcweir       nFormat );
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     // add the necessary space for the frames
215cdf0e10cSrcweir     // and margins
216cdf0e10cSrcweir 
217cdf0e10cSrcweir     lprect->bottom +=
218cdf0e10cSrcweir         m_vMargins +
219cdf0e10cSrcweir         SHADOW_HEIGHT +
220cdf0e10cSrcweir         OUTER_FRAME_WIDTH * 2 +
221cdf0e10cSrcweir         INNER_FRAME_WIDTH * 2;
222cdf0e10cSrcweir 
223cdf0e10cSrcweir     lprect->right +=
224cdf0e10cSrcweir         SHADOW_WIDTH +
225cdf0e10cSrcweir         2 * m_avCharWidth +
226cdf0e10cSrcweir         OUTER_FRAME_WIDTH * 2 +
227cdf0e10cSrcweir         INNER_FRAME_WIDTH * 2;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     SelectObject( hdc, oldFont );
230cdf0e10cSrcweir 
231cdf0e10cSrcweir     ReleaseDC( m_hwnd, hdc );
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir //---------------------------------------------------
235cdf0e10cSrcweir //
236cdf0e10cSrcweir //---------------------------------------------------
237cdf0e10cSrcweir 
adjustWindowSize(sal_Int32 * cx_new,sal_Int32 * cy_new)238cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::adjustWindowSize( sal_Int32* cx_new, sal_Int32* cy_new )
239cdf0e10cSrcweir {
240cdf0e10cSrcweir     OSL_ASSERT( cx_new && cy_new );
241cdf0e10cSrcweir 
242cdf0e10cSrcweir     RECT rect;
243cdf0e10cSrcweir     calcWindowRect( &rect );
244cdf0e10cSrcweir 
245cdf0e10cSrcweir     // adjust the window size
246cdf0e10cSrcweir     SetWindowPos(
247cdf0e10cSrcweir         m_hwnd,
248cdf0e10cSrcweir         NULL,
249cdf0e10cSrcweir         0,
250cdf0e10cSrcweir         0,
251cdf0e10cSrcweir         rect.right,
252cdf0e10cSrcweir         rect.bottom,
253cdf0e10cSrcweir         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
254cdf0e10cSrcweir 
255cdf0e10cSrcweir     *cx_new = rect.right;
256cdf0e10cSrcweir     *cy_new = rect.bottom;
257cdf0e10cSrcweir }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir //---------------------------------------------------
260cdf0e10cSrcweir //
261cdf0e10cSrcweir //---------------------------------------------------
262cdf0e10cSrcweir 
adjustWindowPos(sal_Int32 x,sal_Int32 y,sal_Int32 cx,sal_Int32 cy)263cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::adjustWindowPos(
264cdf0e10cSrcweir     sal_Int32 x, sal_Int32 y, sal_Int32 cx, sal_Int32 cy )
265cdf0e10cSrcweir {
266cdf0e10cSrcweir     int   popX;
267cdf0e10cSrcweir     int   popY;
268cdf0e10cSrcweir     int   popWidth;
269cdf0e10cSrcweir     int   popHeight;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     OSL_ASSERT( m_hwnd );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     HDC hdc = GetDC( m_hwnd );
274cdf0e10cSrcweir 
275cdf0e10cSrcweir     // assuming these are screen coordinates
276cdf0e10cSrcweir     popWidth  = cx;
277cdf0e10cSrcweir     popHeight = cy;
278cdf0e10cSrcweir     popX      = x - ( popWidth / 2 );
279cdf0e10cSrcweir     popY      = y - YOFFSET;
280cdf0e10cSrcweir 
281cdf0e10cSrcweir     int xScreen = GetDeviceCaps( hdc, HORZRES );
282cdf0e10cSrcweir     int yScreen = GetDeviceCaps( hdc, VERTRES );
283cdf0e10cSrcweir 
284cdf0e10cSrcweir     if (popX < 0)
285cdf0e10cSrcweir         popX = 0;
286cdf0e10cSrcweir 
287cdf0e10cSrcweir     if (popY < 0)
288cdf0e10cSrcweir         popY = 0;
289cdf0e10cSrcweir 
290cdf0e10cSrcweir     if ((popX + popWidth) > xScreen)
291cdf0e10cSrcweir         popX = xScreen - popWidth;
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     if ((popY + popHeight) > yScreen)
294cdf0e10cSrcweir         popY = yScreen - popHeight;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     SetWindowPos(
297cdf0e10cSrcweir         m_hwnd,
298cdf0e10cSrcweir         NULL,
299cdf0e10cSrcweir         popX,
300cdf0e10cSrcweir         popY,
301cdf0e10cSrcweir         0,
302cdf0e10cSrcweir         0,
303cdf0e10cSrcweir         SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE );
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     ReleaseDC( m_hwnd, hdc );
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir //---------------------------------------------------
309cdf0e10cSrcweir //
310cdf0e10cSrcweir //---------------------------------------------------
311cdf0e10cSrcweir 
onPaint(HWND hWnd,HDC hdc)312cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::onPaint( HWND hWnd, HDC hdc )
313cdf0e10cSrcweir {
314cdf0e10cSrcweir 	RECT        rc;
315cdf0e10cSrcweir     RECT        rect;
316cdf0e10cSrcweir     HGDIOBJ     hpen, hpenOld;
317cdf0e10cSrcweir     HGDIOBJ     hbrOld;
318cdf0e10cSrcweir     COLORREF    oldBkColor;
319cdf0e10cSrcweir     COLORREF    oldTextColor;
320cdf0e10cSrcweir     HGDIOBJ     oldFont;
321cdf0e10cSrcweir     HGDIOBJ     oldBrush;
322cdf0e10cSrcweir     HGDIOBJ     hBrush;
323cdf0e10cSrcweir 
324cdf0e10cSrcweir     GetClientRect( hWnd, &rc );
325cdf0e10cSrcweir 
326cdf0e10cSrcweir     // draw the black border
327cdf0e10cSrcweir 
328cdf0e10cSrcweir     hBrush   = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
329cdf0e10cSrcweir     oldBrush = SelectObject( hdc, hBrush );
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     hpen    = CreatePen( PS_SOLID, 0, OUTER_FRAME_COLOR );
332cdf0e10cSrcweir     hpenOld = SelectObject( hdc, hpen );
333cdf0e10cSrcweir 
334cdf0e10cSrcweir     Rectangle(  hdc,
335cdf0e10cSrcweir                 rc.left   + OUTER_FRAME_WIDTH,
336cdf0e10cSrcweir                 rc.top    + OUTER_FRAME_WIDTH,
337cdf0e10cSrcweir                 rc.right  - SHADOW_WIDTH,
338cdf0e10cSrcweir                 rc.bottom - SHADOW_HEIGHT);
339cdf0e10cSrcweir 
340cdf0e10cSrcweir     SelectObject( hdc, oldBrush );
341cdf0e10cSrcweir     SelectObject( hdc, hpenOld );
342cdf0e10cSrcweir 
343cdf0e10cSrcweir     DeleteObject( hBrush );
344cdf0e10cSrcweir     DeleteObject( hpen );
345cdf0e10cSrcweir 
346cdf0e10cSrcweir     // draw a light gray border
347cdf0e10cSrcweir 
348cdf0e10cSrcweir     hBrush   = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
349cdf0e10cSrcweir     oldBrush = SelectObject( hdc, hBrush );
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     hpen    = CreatePen( PS_SOLID, 0, INNER_FRAME_COLOR );
352cdf0e10cSrcweir     hpenOld = SelectObject( hdc, hpen );
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     Rectangle(  hdc,
355cdf0e10cSrcweir                 rc.left   + OUTER_FRAME_WIDTH + 1,
356cdf0e10cSrcweir                 rc.top    + OUTER_FRAME_WIDTH + 1,
357cdf0e10cSrcweir                 rc.right  - SHADOW_WIDTH  - OUTER_FRAME_WIDTH,
358cdf0e10cSrcweir                 rc.bottom - SHADOW_HEIGHT - OUTER_FRAME_WIDTH );
359cdf0e10cSrcweir 
360cdf0e10cSrcweir     SelectObject( hdc, oldBrush );
361cdf0e10cSrcweir     SelectObject( hdc, hpenOld );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     DeleteObject( hBrush );
364cdf0e10cSrcweir     DeleteObject( hpen );
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     // Write some text to this window
367cdf0e10cSrcweir 
368cdf0e10cSrcweir     rect.left   = rc.left   + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_hMargins;
369cdf0e10cSrcweir     rect.top    = rc.top    + OUTER_FRAME_WIDTH + INNER_FRAME_WIDTH + 1 + m_vMargins / 2;
370cdf0e10cSrcweir     rect.right  = rc.right  - SHADOW_WIDTH      - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_hMargins;
371cdf0e10cSrcweir     rect.bottom = rc.bottom - SHADOW_HEIGHT     - OUTER_FRAME_WIDTH - INNER_FRAME_WIDTH - m_vMargins / 2;
372cdf0e10cSrcweir 
373cdf0e10cSrcweir     oldBkColor   = SetBkColor( hdc, GetSysColor( COLOR_INFOBK ) );
374cdf0e10cSrcweir     oldTextColor = SetTextColor( hdc, COLOR_INFOTEXT );
375cdf0e10cSrcweir 
376cdf0e10cSrcweir     oldFont = SelectObject( hdc, GetStockObject( DEFAULT_GUI_FONT ) );
377cdf0e10cSrcweir 
378cdf0e10cSrcweir     UINT nFormat = DT_WORDBREAK | DT_EXTERNALLEADING | DT_LEFT;
379cdf0e10cSrcweir 
380cdf0e10cSrcweir     if ( m_HelpText.getLength( ) <= MAX_CHARS_PER_LINE )
381cdf0e10cSrcweir         nFormat |= DT_SINGLELINE;
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     DrawText(
384cdf0e10cSrcweir         hdc,
385cdf0e10cSrcweir         (LPWSTR)m_HelpText.getStr( ),
386cdf0e10cSrcweir         m_HelpText.getLength( ),
387cdf0e10cSrcweir         &rect,
388cdf0e10cSrcweir         nFormat );
389cdf0e10cSrcweir 
390cdf0e10cSrcweir     SelectObject( hdc, oldFont );
391cdf0e10cSrcweir     SetTextColor( hdc, oldTextColor );
392cdf0e10cSrcweir     SetBkColor( hdc, oldBkColor );
393cdf0e10cSrcweir 
394cdf0e10cSrcweir     // set text color and text background color
395cdf0e10cSrcweir     // see MSDN PatBlt
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     oldBkColor   = SetBkColor( hdc, RGB( 0, 0, 0 ) );
398cdf0e10cSrcweir     oldTextColor = SetTextColor( hdc, RGB( 255, 255, 255 ) );
399cdf0e10cSrcweir 
400cdf0e10cSrcweir     // Get our brush for the shadow
401cdf0e10cSrcweir 
402cdf0e10cSrcweir     UnrealizeObject( m_hBrushShadow );
403cdf0e10cSrcweir     hbrOld = SelectObject( hdc, m_hBrushShadow );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir     // bottom shadow
406cdf0e10cSrcweir 
407cdf0e10cSrcweir     PatBlt(hdc,
408cdf0e10cSrcweir            rc.left + SHADOW_OFFSET,
409cdf0e10cSrcweir            rc.bottom - SHADOW_HEIGHT,
410cdf0e10cSrcweir            rc.right - SHADOW_OFFSET - SHADOW_WIDTH,
411cdf0e10cSrcweir            SHADOW_HEIGHT,
412cdf0e10cSrcweir            0xA000C9);
413cdf0e10cSrcweir 
414cdf0e10cSrcweir     // right-side shadow
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     PatBlt(hdc,
417cdf0e10cSrcweir            rc.right - SHADOW_WIDTH,
418cdf0e10cSrcweir            rc.top + SHADOW_OFFSET,
419cdf0e10cSrcweir            SHADOW_WIDTH,
420cdf0e10cSrcweir            rc.bottom - SHADOW_OFFSET,
421cdf0e10cSrcweir            0xA000C9);
422cdf0e10cSrcweir 
423cdf0e10cSrcweir     SelectObject(hdc, hbrOld);
424cdf0e10cSrcweir     SetTextColor( hdc, oldTextColor );
425cdf0e10cSrcweir     SetBkColor( hdc, oldBkColor );
426cdf0e10cSrcweir }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir //---------------------------------------------------
429cdf0e10cSrcweir //
430cdf0e10cSrcweir //---------------------------------------------------
431cdf0e10cSrcweir 
onNcDestroy()432cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::onNcDestroy()
433cdf0e10cSrcweir {
434cdf0e10cSrcweir     m_hwnd = NULL;
435cdf0e10cSrcweir }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir //---------------------------------------------------
438cdf0e10cSrcweir //
439cdf0e10cSrcweir //---------------------------------------------------
440cdf0e10cSrcweir 
onCreate(HWND hwnd)441cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::onCreate( HWND hwnd )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir     m_hwnd = hwnd;
444cdf0e10cSrcweir 
445cdf0e10cSrcweir     HDC hdc = GetDC( m_hwnd );
446cdf0e10cSrcweir 
447cdf0e10cSrcweir     HGDIOBJ oldFont = SelectObject(
448cdf0e10cSrcweir         hdc, GetStockObject( DEFAULT_GUI_FONT ) );
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     TEXTMETRIC tm;
451cdf0e10cSrcweir     GetTextMetrics( hdc, &tm );
452cdf0e10cSrcweir 
453cdf0e10cSrcweir     m_avCharWidth  = tm.tmAveCharWidth;
454cdf0e10cSrcweir     m_avCharHeight = tm.tmHeight;
455cdf0e10cSrcweir 
456cdf0e10cSrcweir     if ( 0 == m_hMargins )
457cdf0e10cSrcweir         m_hMargins = m_avCharWidth;
458cdf0e10cSrcweir 
459cdf0e10cSrcweir     if ( 0 == m_vMargins )
460cdf0e10cSrcweir         m_vMargins = m_avCharHeight;
461cdf0e10cSrcweir 
462cdf0e10cSrcweir     SelectObject( hdc, oldFont );
463cdf0e10cSrcweir 
464cdf0e10cSrcweir     ReleaseDC( m_hwnd, hdc );
465cdf0e10cSrcweir }
466cdf0e10cSrcweir 
467cdf0e10cSrcweir //---------------------------------------------------
468cdf0e10cSrcweir //
469cdf0e10cSrcweir //---------------------------------------------------
470cdf0e10cSrcweir 
WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)471cdf0e10cSrcweir LRESULT CALLBACK CHelpPopupWindow::WndProc(
472cdf0e10cSrcweir     HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
473cdf0e10cSrcweir {
474cdf0e10cSrcweir 	LRESULT lResult = 0;
475cdf0e10cSrcweir 
476cdf0e10cSrcweir     switch ( uMsg )
477cdf0e10cSrcweir     {
478cdf0e10cSrcweir         case WM_CREATE:
479cdf0e10cSrcweir             {
480cdf0e10cSrcweir                 LPCREATESTRUCT lpcs =
481cdf0e10cSrcweir                     reinterpret_cast< LPCREATESTRUCT >( lParam );
482cdf0e10cSrcweir 
483cdf0e10cSrcweir                 OSL_ASSERT( lpcs->lpCreateParams );
484cdf0e10cSrcweir 
485cdf0e10cSrcweir                 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
486cdf0e10cSrcweir                     lpcs->lpCreateParams );
487cdf0e10cSrcweir 
488cdf0e10cSrcweir                 // connect the instance handle to the window
489cdf0e10cSrcweir                 SetProp( hWnd, CURRENT_INSTANCE, pImpl );
490cdf0e10cSrcweir 
491cdf0e10cSrcweir                 pImpl->onCreate( hWnd );
492cdf0e10cSrcweir 
493cdf0e10cSrcweir                 // capture mouse and keybord events
494cdf0e10cSrcweir                 SetCapture( hWnd );
495cdf0e10cSrcweir              }
496cdf0e10cSrcweir         break;
497cdf0e10cSrcweir 
498cdf0e10cSrcweir         case WM_PAINT:
499cdf0e10cSrcweir             {
500cdf0e10cSrcweir                 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
501cdf0e10cSrcweir                 GetProp( hWnd, CURRENT_INSTANCE ) );
502cdf0e10cSrcweir 
503cdf0e10cSrcweir                 OSL_ASSERT( pImpl );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir                 PAINTSTRUCT ps;
506cdf0e10cSrcweir 
507cdf0e10cSrcweir                 BeginPaint(hWnd, &ps);
508cdf0e10cSrcweir                 pImpl->onPaint( hWnd, ps.hdc );
509cdf0e10cSrcweir                 EndPaint(hWnd, &ps);
510cdf0e10cSrcweir             }
511cdf0e10cSrcweir          break;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir          case WM_NCDESTROY:
514cdf0e10cSrcweir             {
515cdf0e10cSrcweir                 // RemoveProp returns the saved value on success
516cdf0e10cSrcweir                 CHelpPopupWindow* pImpl = reinterpret_cast< CHelpPopupWindow* >(
517cdf0e10cSrcweir                     RemoveProp( hWnd, CURRENT_INSTANCE ) );
518cdf0e10cSrcweir 
519cdf0e10cSrcweir                 OSL_ASSERT( pImpl );
520cdf0e10cSrcweir 
521cdf0e10cSrcweir                 pImpl->onNcDestroy();
522cdf0e10cSrcweir             }
523cdf0e10cSrcweir          break;
524cdf0e10cSrcweir 
525cdf0e10cSrcweir          case WM_LBUTTONDOWN:
526cdf0e10cSrcweir          case WM_KEYDOWN:
527cdf0e10cSrcweir          case WM_SYSKEYDOWN:
528cdf0e10cSrcweir          case WM_MBUTTONDOWN:
529cdf0e10cSrcweir          case WM_RBUTTONDOWN:
530cdf0e10cSrcweir              ReleaseCapture();
531cdf0e10cSrcweir              DestroyWindow(hWnd);
532cdf0e10cSrcweir          break;
533cdf0e10cSrcweir 
534cdf0e10cSrcweir          default:
535cdf0e10cSrcweir              return DefWindowProc(hWnd, uMsg, wParam, lParam);
536cdf0e10cSrcweir        }
537cdf0e10cSrcweir 
538cdf0e10cSrcweir     return lResult;
539cdf0e10cSrcweir }
540cdf0e10cSrcweir 
541cdf0e10cSrcweir //---------------------------------------------------
542cdf0e10cSrcweir //
543cdf0e10cSrcweir //---------------------------------------------------
544cdf0e10cSrcweir 
RegisterWindowClass()545cdf0e10cSrcweir ATOM SAL_CALL CHelpPopupWindow::RegisterWindowClass( )
546cdf0e10cSrcweir {
547cdf0e10cSrcweir     osl::MutexGuard aGuard( s_Mutex );
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     if ( 0 == s_ClassAtom )
550cdf0e10cSrcweir     {
551cdf0e10cSrcweir         // register the window class
552cdf0e10cSrcweir 	    WNDCLASSEX wndClsEx;
553cdf0e10cSrcweir 
554cdf0e10cSrcweir 	    ZeroMemory(&wndClsEx, sizeof(wndClsEx));
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 	    wndClsEx.cbSize        = sizeof(wndClsEx);
557cdf0e10cSrcweir 	    wndClsEx.lpfnWndProc   = CHelpPopupWindow::WndProc;
558cdf0e10cSrcweir 	    wndClsEx.hInstance     = m_hInstance;
559cdf0e10cSrcweir         wndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
560cdf0e10cSrcweir 	    wndClsEx.hbrBackground = (HBRUSH)GetStockObject( NULL_BRUSH );
561cdf0e10cSrcweir 	    wndClsEx.lpszClassName = HELPPOPUPWND_CLASS_NAME;
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 	    // register the preview window class
564cdf0e10cSrcweir 	    // !!! Win95 -   the window class will be unregistered automaticly
565cdf0e10cSrcweir 	    //			     if the dll is unloaded
566cdf0e10cSrcweir 	    //     Win2000 - the window class must be unregistered manually
567cdf0e10cSrcweir 	    //				 if the dll is unloaded
568cdf0e10cSrcweir 	    s_ClassAtom = RegisterClassEx( &wndClsEx );
569cdf0e10cSrcweir         OSL_ASSERT(s_ClassAtom);
570cdf0e10cSrcweir     }
571cdf0e10cSrcweir 
572cdf0e10cSrcweir     // increment the register class counter
573cdf0e10cSrcweir     // so that we keep track of the number
574cdf0e10cSrcweir     // of class registrations
575cdf0e10cSrcweir     if (0 != s_ClassAtom)
576cdf0e10cSrcweir         s_RegisterWndClassCount++;
577cdf0e10cSrcweir 
578cdf0e10cSrcweir     return s_ClassAtom;
579cdf0e10cSrcweir }
580cdf0e10cSrcweir 
581cdf0e10cSrcweir //---------------------------------------------------
582cdf0e10cSrcweir //
583cdf0e10cSrcweir //---------------------------------------------------
584cdf0e10cSrcweir 
UnregisterWindowClass()585cdf0e10cSrcweir void SAL_CALL CHelpPopupWindow::UnregisterWindowClass( )
586cdf0e10cSrcweir {
587cdf0e10cSrcweir     osl::MutexGuard aGuard( s_Mutex );
588cdf0e10cSrcweir 
589cdf0e10cSrcweir     OSL_ASSERT( ( (0 != s_ClassAtom) && (s_RegisterWndClassCount > 0)) ||
590cdf0e10cSrcweir                 ( (0 == s_ClassAtom) && (0 == s_RegisterWndClassCount) ) );
591cdf0e10cSrcweir 
592cdf0e10cSrcweir     // update the register class counter
593cdf0e10cSrcweir     // and unregister the window class if
594cdf0e10cSrcweir     // counter drops to zero
595cdf0e10cSrcweir     if ( 0 != s_ClassAtom )
596cdf0e10cSrcweir     {
597cdf0e10cSrcweir         s_RegisterWndClassCount--;
598cdf0e10cSrcweir         OSL_ASSERT( s_RegisterWndClassCount >= 0 );
599cdf0e10cSrcweir     }
600cdf0e10cSrcweir 
601cdf0e10cSrcweir     if ( 0 == s_RegisterWndClassCount )
602cdf0e10cSrcweir     {
603cdf0e10cSrcweir         if ( !UnregisterClass(
604cdf0e10cSrcweir                  (LPCTSTR)MAKELONG( s_ClassAtom, 0 ), m_hInstance ) )
605cdf0e10cSrcweir         {
606cdf0e10cSrcweir             OSL_ENSURE( false, "unregister window class failed" );
607cdf0e10cSrcweir         }
608cdf0e10cSrcweir 
609cdf0e10cSrcweir         s_ClassAtom = 0;
610cdf0e10cSrcweir     }
611cdf0e10cSrcweir }
612