]> git.sesse.net Git - vlc/blob - modules/gui/skins2/win32/win32_factory.cpp
added a function to minimize VLC (check win32 compilation)
[vlc] / modules / gui / skins2 / win32 / win32_factory.cpp
1 /*****************************************************************************
2  * win32_factory.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA  02111, 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_loop.hpp"
33
34
35 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
36 {
37     // Get pointer to thread info: should only work with the parent window
38     intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
39         GWLP_USERDATA );
40
41     // If doesn't exist, treat windows message normally
42     if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
43     {
44         return DefWindowProc( hwnd, uMsg, wParam, lParam );
45     }
46
47     // Here we know we are getting a message for the parent window, since it is
48     // the only one to store p_intf...
49     // Yes, it is a kludge :)
50
51 //Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( p_intf );
52 //msg_Err( p_intf, "Parent window %p %p %u %i\n", pFactory->m_hParentWindow, hwnd, uMsg, wParam );
53     // If Window is parent window
54     // XXX: this test isn't needed, see the kludge above...
55 //    if( hwnd == pFactory->m_hParentWindow )
56     {
57         if( uMsg == WM_SYSCOMMAND )
58         {
59             // If closing parent window
60             if( wParam == SC_CLOSE )
61             {
62                 Win32Loop *pLoop = (Win32Loop*)Win32Loop::instance( p_intf );
63                 pLoop->exit();
64                 return 0;
65             }
66             else
67             {
68                 msg_Err( p_intf, "WM_SYSCOMMAND %i", wParam );
69             }
70 //            if( (Event *)wParam != NULL )
71 //                ( (Event *)wParam )->SendEvent();
72 //            return 0;
73         }
74     }
75
76     // If hwnd does not match any window or message not processed
77     return DefWindowProc( hwnd, uMsg, wParam, lParam );
78 }
79
80
81 Win32Factory::Win32Factory( intf_thread_t *pIntf ):
82     OSFactory( pIntf ), TransparentBlt( NULL ), AlphaBlend( NULL ),
83     SetLayeredWindowAttributes( NULL ), m_hParentWindow( NULL ),
84     m_dirSep( "\\" )
85 {
86     // see init()
87 }
88
89
90 bool Win32Factory::init()
91 {
92     // Get instance handle
93     m_hInst = GetModuleHandle( NULL );
94     if( m_hInst == NULL )
95     {
96         msg_Err( getIntf(), "Cannot get module handle" );
97     }
98
99     // Create window class
100     WNDCLASS skinWindowClass;
101     skinWindowClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
102     skinWindowClass.lpfnWndProc = (WNDPROC) Win32Proc;
103     skinWindowClass.lpszClassName = "SkinWindowClass";
104     skinWindowClass.lpszMenuName = NULL;
105     skinWindowClass.cbClsExtra = 0;
106     skinWindowClass.cbWndExtra = 0;
107     skinWindowClass.hbrBackground = HBRUSH (COLOR_WINDOW);
108     skinWindowClass.hCursor = LoadCursor( NULL , IDC_ARROW );
109     skinWindowClass.hIcon = LoadIcon( m_hInst, "VLC_ICON" );
110     skinWindowClass.hInstance = m_hInst;
111
112     // Register class and check it
113     if( !RegisterClass( &skinWindowClass ) )
114     {
115         WNDCLASS wndclass;
116
117         // Check why it failed. If it's because the class already exists
118         // then fine, otherwise return with an error.
119         if( !GetClassInfo( m_hInst, "SkinWindowClass", &wndclass ) )
120         {
121             msg_Err( getIntf(), "Cannot register window class" );
122             return false;
123         }
124     }
125
126     // Create Window
127     m_hParentWindow = CreateWindowEx( WS_EX_APPWINDOW, "SkinWindowClass",
128         "VLC media player", WS_SYSMENU, -200, -200, 0, 0, 0, 0, m_hInst, 0 );
129     if( m_hParentWindow == NULL )
130     {
131         msg_Err( getIntf(), "Cannot create parent window" );
132         return false;
133     }
134
135     // We do it this way otherwise CreateWindowEx will fail
136     // if WS_EX_LAYERED is not supported
137     SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
138                       GetWindowLong( m_hParentWindow, GWL_EXSTYLE )
139                       | WS_EX_LAYERED );
140
141     // Store with it a pointer to the interface thread
142     SetWindowLongPtr( m_hParentWindow, GWLP_USERDATA, (LONG_PTR)getIntf() );
143     ShowWindow( m_hParentWindow, SW_SHOW );
144
145     // Initialize the OLE library (for drag & drop)
146     OleInitialize( NULL );
147
148     // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
149     m_hMsimg32 = LoadLibrary( "msimg32.dll" );
150     if( !m_hMsimg32 ||
151         !( TransparentBlt =
152             (BOOL (WINAPI*)(HDC, int, int, int, int,
153                             HDC, int, int, int, int, unsigned int))
154             GetProcAddress( m_hMsimg32, "TransparentBlt" ) ) )
155     {
156         TransparentBlt = NULL;
157         msg_Dbg( getIntf(), "Couldn't find TransparentBlt(), "
158                  "falling back to BitBlt()" );
159     }
160     if( !m_hMsimg32 ||
161         !( AlphaBlend =
162             (BOOL (WINAPI*)( HDC, int, int, int, int, HDC, int, int,
163                               int, int, BLENDFUNCTION ))
164             GetProcAddress( m_hMsimg32, "AlphaBlend" ) ) )
165     {
166         AlphaBlend = NULL;
167         msg_Dbg( getIntf(), "Couldn't find AlphaBlend()" );
168     }
169
170     // Idem for user32.dll and SetLayeredWindowAttributes()
171     m_hUser32 = LoadLibrary( "user32.dll" );
172     if( !m_hUser32 ||
173         !( SetLayeredWindowAttributes =
174             (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
175             GetProcAddress( m_hUser32, "SetLayeredWindowAttributes" ) ) )
176     {
177         SetLayeredWindowAttributes = NULL;
178         msg_Dbg( getIntf(), "Couldn't find SetLayeredWindowAttributes()" );
179     }
180
181     // Initialize the resource path
182     m_resourcePath.push_back( (string)getIntf()->p_vlc->psz_homedir +
183                                "\\" + CONFIG_DIR + "\\skins2" );
184     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
185                               "\\skins2" );
186     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
187                               "\\share\\skins2" );
188
189     // All went well
190     return true;
191 }
192
193
194 Win32Factory::~Win32Factory()
195 {
196     // Uninitialize the OLE library
197     OleUninitialize();
198
199     if( m_hParentWindow ) DestroyWindow( m_hParentWindow );
200
201     // Unload msimg32.dll and user32.dll
202     if( m_hMsimg32 )
203         FreeLibrary( m_hMsimg32 );
204     if( m_hUser32 )
205         FreeLibrary( m_hUser32 );
206 }
207
208
209 OSGraphics *Win32Factory::createOSGraphics( int width, int height )
210 {
211     return new Win32Graphics( getIntf(), width, height );
212 }
213
214
215 OSLoop *Win32Factory::getOSLoop()
216 {
217     return Win32Loop::instance( getIntf() );
218 }
219
220
221 void Win32Factory::destroyOSLoop()
222 {
223     Win32Loop::destroy( getIntf() );
224 }
225
226 void Win32Factory::minimize()
227 {
228 }
229
230 OSTimer *Win32Factory::createOSTimer( const Callback &rCallback )
231 {
232     return new Win32Timer( getIntf(), rCallback, m_hParentWindow );
233 }
234
235
236 OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
237                                         bool playOnDrop, OSWindow *pParent )
238 {
239     return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
240                             dragDrop, playOnDrop, (Win32Window*)pParent );
241 }
242
243
244 OSTooltip *Win32Factory::createOSTooltip()
245 {
246     return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
247 }
248
249
250 int Win32Factory::getScreenWidth() const
251 {
252     return GetSystemMetrics(SM_CXSCREEN);
253
254 }
255
256
257 int Win32Factory::getScreenHeight() const
258 {
259     return GetSystemMetrics(SM_CYSCREEN);
260 }
261
262
263 Rect Win32Factory::getWorkArea() const
264 {
265     RECT r;
266     SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
267     // Fill a Rect object
268     Rect rect( r.left, r.top, r.right, r.bottom );
269     return rect;
270 }
271
272
273 void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
274 {
275     POINT mousePos;
276     GetCursorPos( &mousePos );
277     rXPos = mousePos.x;
278     rYPos = mousePos.y;
279 }
280
281
282 void Win32Factory::changeCursor( CursorType_t type ) const
283 {
284     LPCTSTR id;
285     switch( type )
286     {
287         case kDefaultArrow:
288             id = IDC_ARROW;
289             break;
290         case kResizeNWSE:
291             id = IDC_SIZENWSE;
292             break;
293         case kResizeNS:
294             id = IDC_SIZENS;
295             break;
296         case kResizeWE:
297             id = IDC_SIZEWE;
298             break;
299         case kResizeNESW:
300             id = IDC_SIZENESW;
301             break;
302         default:
303             id = IDC_ARROW;
304             break;
305     }
306
307     HCURSOR hCurs = LoadCursor( NULL, id );
308     SetCursor( hCurs );
309 }
310
311
312 void Win32Factory::rmDir( const string &rPath )
313 {
314     WIN32_FIND_DATA find;
315     string file;
316     string findFiles = rPath + "\\*";
317     HANDLE handle    = FindFirstFile( findFiles.c_str(), &find );
318
319     while( handle != INVALID_HANDLE_VALUE )
320     {
321         // If file is neither "." nor ".."
322         if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
323         {
324             // Set file name
325             file = rPath + "\\" + (string)find.cFileName;
326
327             // If file is a directory, delete it recursively
328             if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
329             {
330                 rmDir( file );
331             }
332             // Else, it is a file so simply delete it
333             else
334             {
335                 DeleteFile( file.c_str() );
336             }
337         }
338
339         // If no more file in directory, exit while
340         if( !FindNextFile( handle, &find ) )
341             break;
342     }
343
344     // Now directory is empty so can be removed
345     FindClose( handle );
346     RemoveDirectory( rPath.c_str() );
347 }
348
349
350 #endif