]> git.sesse.net Git - vlc/blob - modules/gui/skins2/win32/win32_factory.cpp
Skins strings (Refs:#438)
[vlc] / modules / gui / skins2 / win32 / win32_factory.cpp
1 /*****************************************************************************
2  * win32_factory.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef WIN32_SKINS
26
27 #include "win32_factory.hpp"
28 #include "win32_graphics.hpp"
29 #include "win32_timer.hpp"
30 #include "win32_window.hpp"
31 #include "win32_tooltip.hpp"
32 #include "win32_popup.hpp"
33 #include "win32_loop.hpp"
34 #include "../src/theme.hpp"
35
36
37 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
38 {
39     // Get pointer to thread info: should only work with the parent window
40     intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
41         GWLP_USERDATA );
42
43     // If doesn't exist, treat windows message normally
44     if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
45     {
46         return DefWindowProc( hwnd, uMsg, wParam, lParam );
47     }
48
49     // Here we know we are getting a message for the parent window, since it is
50     // the only one to store p_intf...
51     // Yes, it is a kludge :)
52
53 //Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( p_intf );
54 //msg_Err( p_intf, "Parent window %p %p %u %i\n", pFactory->m_hParentWindow, hwnd, uMsg, wParam );
55     // If Window is parent window
56     // XXX: this test isn't needed, see the kludge above...
57 //    if( hwnd == pFactory->m_hParentWindow )
58     {
59         if( uMsg == WM_SYSCOMMAND )
60         {
61             // If closing parent window
62             if( wParam == SC_CLOSE )
63             {
64                 Win32Loop *pLoop = (Win32Loop*)Win32Loop::instance( p_intf );
65                 pLoop->exit();
66                 return 0;
67             }
68             else
69             {
70                 msg_Err( p_intf, "WM_SYSCOMMAND %i", wParam );
71             }
72 //            if( (Event *)wParam != NULL )
73 //                ( (Event *)wParam )->SendEvent();
74 //            return 0;
75         }
76     }
77
78     // If hwnd does not match any window or message not processed
79     return DefWindowProc( hwnd, uMsg, wParam, lParam );
80 }
81
82
83 Win32Factory::Win32Factory( intf_thread_t *pIntf ):
84     OSFactory( pIntf ), TransparentBlt( NULL ), AlphaBlend( NULL ),
85     SetLayeredWindowAttributes( NULL ), m_hParentWindow( NULL ),
86     m_dirSep( "\\" )
87 {
88     // see init()
89 }
90
91
92 bool Win32Factory::init()
93 {
94     // Get instance handle
95     m_hInst = GetModuleHandle( NULL );
96     if( m_hInst == NULL )
97     {
98         msg_Err( getIntf(), "Cannot get module handle" );
99     }
100
101     // Create window class
102     WNDCLASS skinWindowClass;
103     skinWindowClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
104     skinWindowClass.lpfnWndProc = (WNDPROC) Win32Proc;
105     skinWindowClass.lpszClassName = _T("SkinWindowClass");
106     skinWindowClass.lpszMenuName = NULL;
107     skinWindowClass.cbClsExtra = 0;
108     skinWindowClass.cbWndExtra = 0;
109     skinWindowClass.hbrBackground = NULL;
110     skinWindowClass.hCursor = LoadCursor( NULL , IDC_ARROW );
111     skinWindowClass.hIcon = LoadIcon( m_hInst, _T("VLC_ICON") );
112     skinWindowClass.hInstance = m_hInst;
113
114     // Register class and check it
115     if( !RegisterClass( &skinWindowClass ) )
116     {
117         WNDCLASS wndclass;
118
119         // Check why it failed. If it's because the class already exists
120         // then fine, otherwise return with an error.
121         if( !GetClassInfo( m_hInst, _T("SkinWindowClass"), &wndclass ) )
122         {
123             msg_Err( getIntf(), "cannot register window class" );
124             return false;
125         }
126     }
127
128     // Create Window
129     m_hParentWindow = CreateWindowEx( WS_EX_APPWINDOW, _T("SkinWindowClass"),
130         _T("VLC media player"), WS_SYSMENU|WS_POPUP,
131         -200, -200, 0, 0, 0, 0, m_hInst, 0 );
132     if( m_hParentWindow == NULL )
133     {
134         msg_Err( getIntf(), "cannot create parent window" );
135         return false;
136     }
137
138     // We do it this way otherwise CreateWindowEx will fail
139     // if WS_EX_LAYERED is not supported
140     SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
141                       GetWindowLong( m_hParentWindow, GWL_EXSTYLE ) |
142                       WS_EX_LAYERED );
143
144     // Store with it a pointer to the interface thread
145     SetWindowLongPtr( m_hParentWindow, GWLP_USERDATA, (LONG_PTR)getIntf() );
146     ShowWindow( m_hParentWindow, SW_SHOW );
147
148     // Initialize the OLE library (for drag & drop)
149     OleInitialize( NULL );
150
151     // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
152     m_hMsimg32 = LoadLibrary( _T("msimg32.dll") );
153     if( !m_hMsimg32 ||
154         !( TransparentBlt =
155             (BOOL (WINAPI*)(HDC, int, int, int, int,
156                             HDC, int, int, int, int, unsigned int))
157             GetProcAddress( m_hMsimg32, _T("TransparentBlt") ) ) )
158     {
159         TransparentBlt = NULL;
160         msg_Dbg( getIntf(), "couldn't find TransparentBlt(), "
161                  "falling back to BitBlt()" );
162     }
163     if( !m_hMsimg32 ||
164         !( AlphaBlend =
165             (BOOL (WINAPI*)( HDC, int, int, int, int, HDC, int, int,
166                               int, int, BLENDFUNCTION ))
167             GetProcAddress( m_hMsimg32, _T("AlphaBlend") ) ) )
168     {
169         AlphaBlend = NULL;
170         msg_Dbg( getIntf(), "couldn't find AlphaBlend()" );
171     }
172
173     // Idem for user32.dll and SetLayeredWindowAttributes()
174     m_hUser32 = LoadLibrary( _T("user32.dll") );
175     if( !m_hUser32 ||
176         !( SetLayeredWindowAttributes =
177             (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
178             GetProcAddress( m_hUser32, _T("SetLayeredWindowAttributes") ) ) )
179     {
180         SetLayeredWindowAttributes = NULL;
181         msg_Dbg( getIntf(), "couldn't find SetLayeredWindowAttributes()" );
182     }
183
184     // Initialize the resource path
185     m_resourcePath.push_back( (string)getIntf()->p_vlc->psz_homedir +
186                                "\\" + CONFIG_DIR + "\\skins" );
187     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
188                               "\\skins" );
189     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
190                               "\\skins2" );
191     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
192                               "\\share\\skins" );
193     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
194                               "\\share\\skins2" );
195
196     // All went well
197     return true;
198 }
199
200
201 Win32Factory::~Win32Factory()
202 {
203     // Uninitialize the OLE library
204     OleUninitialize();
205
206     if( m_hParentWindow ) DestroyWindow( m_hParentWindow );
207
208     // Unload msimg32.dll and user32.dll
209     if( m_hMsimg32 )
210         FreeLibrary( m_hMsimg32 );
211     if( m_hUser32 )
212         FreeLibrary( m_hUser32 );
213 }
214
215
216 OSGraphics *Win32Factory::createOSGraphics( int width, int height )
217 {
218     return new Win32Graphics( getIntf(), width, height );
219 }
220
221
222 OSLoop *Win32Factory::getOSLoop()
223 {
224     return Win32Loop::instance( getIntf() );
225 }
226
227
228 void Win32Factory::destroyOSLoop()
229 {
230     Win32Loop::destroy( getIntf() );
231 }
232
233 void Win32Factory::minimize()
234 {
235     /* Make sure no tooltip is visible first */
236     getIntf()->p_sys->p_theme->getWindowManager().hideTooltip();
237
238     ShowWindow( m_hParentWindow, SW_MINIMIZE );
239 }
240
241 OSTimer *Win32Factory::createOSTimer( CmdGeneric &rCmd )
242 {
243     return new Win32Timer( getIntf(), rCmd, m_hParentWindow );
244 }
245
246
247 OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
248                                         bool playOnDrop, OSWindow *pParent )
249 {
250     return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
251                             dragDrop, playOnDrop, (Win32Window*)pParent );
252 }
253
254
255 OSTooltip *Win32Factory::createOSTooltip()
256 {
257     return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
258 }
259
260
261 OSPopup *Win32Factory::createOSPopup()
262 {
263     // XXX FIXME: this way of getting the handle really sucks!
264     // In fact, the clean way would be to have in Builder::addPopup() a call
265     // to pPopup->associateToWindow() (to be written)... but the problem is
266     // that there is no way to access the OS-dependent window handle from a
267     // GenericWindow (we cannot eevn access the OSWindow).
268     if( m_windowMap.begin() == m_windowMap.end() )
269     {
270         msg_Err( getIntf(), "no window has been created before the popup!" );
271         return NULL;
272     }
273
274     return new Win32Popup( getIntf(), m_windowMap.begin()->first );
275 }
276
277
278 int Win32Factory::getScreenWidth() const
279 {
280     return GetSystemMetrics(SM_CXSCREEN);
281
282 }
283
284
285 int Win32Factory::getScreenHeight() const
286 {
287     return GetSystemMetrics(SM_CYSCREEN);
288 }
289
290
291 Rect Win32Factory::getWorkArea() const
292 {
293     RECT r;
294     SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
295     // Fill a Rect object
296     Rect rect( r.left, r.top, r.right, r.bottom );
297     return rect;
298 }
299
300
301 void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
302 {
303     POINT mousePos;
304     GetCursorPos( &mousePos );
305     rXPos = mousePos.x;
306     rYPos = mousePos.y;
307 }
308
309
310 void Win32Factory::changeCursor( CursorType_t type ) const
311 {
312     LPCTSTR id;
313     switch( type )
314     {
315         case kDefaultArrow:
316             id = IDC_ARROW;
317             break;
318         case kResizeNWSE:
319             id = IDC_SIZENWSE;
320             break;
321         case kResizeNS:
322             id = IDC_SIZENS;
323             break;
324         case kResizeWE:
325             id = IDC_SIZEWE;
326             break;
327         case kResizeNESW:
328             id = IDC_SIZENESW;
329             break;
330         default:
331             id = IDC_ARROW;
332             break;
333     }
334
335     HCURSOR hCurs = LoadCursor( NULL, id );
336     SetCursor( hCurs );
337 }
338
339
340 void Win32Factory::rmDir( const string &rPath )
341 {
342     WIN32_FIND_DATA find;
343     string file;
344     string findFiles = rPath + "\\*";
345     HANDLE handle    = FindFirstFile( findFiles.c_str(), &find );
346
347     while( handle != INVALID_HANDLE_VALUE )
348     {
349         // If file is neither "." nor ".."
350         if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
351         {
352             // Set file name
353             file = rPath + "\\" + (string)find.cFileName;
354
355             // If file is a directory, delete it recursively
356             if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
357             {
358                 rmDir( file );
359             }
360             // Else, it is a file so simply delete it
361             else
362             {
363                 DeleteFile( file.c_str() );
364             }
365         }
366
367         // If no more file in directory, exit while
368         if( !FindNextFile( handle, &find ) )
369             break;
370     }
371
372     // Now directory is empty so can be removed
373     FindClose( handle );
374     RemoveDirectory( rPath.c_str() );
375 }
376
377 #endif