1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
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.
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.
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 *****************************************************************************/
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"
37 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
39 // Get pointer to thread info: should only work with the parent window
40 intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
43 // If doesn't exist, treat windows message normally
44 if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
46 return DefWindowProc( hwnd, uMsg, wParam, lParam );
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 :)
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 )
59 if( uMsg == WM_SYSCOMMAND )
61 // If closing parent window
62 if( wParam == SC_CLOSE )
64 Win32Loop *pLoop = (Win32Loop*)Win32Loop::instance( p_intf );
70 msg_Err( p_intf, "WM_SYSCOMMAND %i", wParam );
72 // if( (Event *)wParam != NULL )
73 // ( (Event *)wParam )->SendEvent();
78 // If hwnd does not match any window or message not processed
79 return DefWindowProc( hwnd, uMsg, wParam, lParam );
83 Win32Factory::Win32Factory( intf_thread_t *pIntf ):
84 OSFactory( pIntf ), TransparentBlt( NULL ), AlphaBlend( NULL ),
85 SetLayeredWindowAttributes( NULL ), m_hParentWindow( NULL ),
92 bool Win32Factory::init()
94 // Get instance handle
95 m_hInst = GetModuleHandle( NULL );
98 msg_Err( getIntf(), "Cannot get module handle" );
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;
114 // Register class and check it
115 if( !RegisterClass( &skinWindowClass ) )
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 ) )
123 msg_Err( getIntf(), "cannot register window class" );
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 )
134 msg_Err( getIntf(), "cannot create parent window" );
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 ) |
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 );
148 // Initialize the OLE library (for drag & drop)
149 OleInitialize( NULL );
151 // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
152 m_hMsimg32 = LoadLibrary( _T("msimg32.dll") );
155 (BOOL (WINAPI*)(HDC, int, int, int, int,
156 HDC, int, int, int, int, unsigned int))
157 GetProcAddress( m_hMsimg32, _T("TransparentBlt") ) ) )
159 TransparentBlt = NULL;
160 msg_Dbg( getIntf(), "couldn't find TransparentBlt(), "
161 "falling back to BitBlt()" );
165 (BOOL (WINAPI*)( HDC, int, int, int, int, HDC, int, int,
166 int, int, BLENDFUNCTION ))
167 GetProcAddress( m_hMsimg32, _T("AlphaBlend") ) ) )
170 msg_Dbg( getIntf(), "couldn't find AlphaBlend()" );
173 // Idem for user32.dll and SetLayeredWindowAttributes()
174 m_hUser32 = LoadLibrary( _T("user32.dll") );
176 !( SetLayeredWindowAttributes =
177 (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
178 GetProcAddress( m_hUser32, _T("SetLayeredWindowAttributes") ) ) )
180 SetLayeredWindowAttributes = NULL;
181 msg_Dbg( getIntf(), "couldn't find SetLayeredWindowAttributes()" );
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 +
189 m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
191 m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
193 m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
201 Win32Factory::~Win32Factory()
203 // Uninitialize the OLE library
206 if( m_hParentWindow ) DestroyWindow( m_hParentWindow );
208 // Unload msimg32.dll and user32.dll
210 FreeLibrary( m_hMsimg32 );
212 FreeLibrary( m_hUser32 );
216 OSGraphics *Win32Factory::createOSGraphics( int width, int height )
218 return new Win32Graphics( getIntf(), width, height );
222 OSLoop *Win32Factory::getOSLoop()
224 return Win32Loop::instance( getIntf() );
228 void Win32Factory::destroyOSLoop()
230 Win32Loop::destroy( getIntf() );
233 void Win32Factory::minimize()
235 /* Make sure no tooltip is visible first */
236 getIntf()->p_sys->p_theme->getWindowManager().hideTooltip();
238 ShowWindow( m_hParentWindow, SW_MINIMIZE );
241 OSTimer *Win32Factory::createOSTimer( CmdGeneric &rCmd )
243 return new Win32Timer( getIntf(), rCmd, m_hParentWindow );
247 OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
248 bool playOnDrop, OSWindow *pParent )
250 return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
251 dragDrop, playOnDrop, (Win32Window*)pParent );
255 OSTooltip *Win32Factory::createOSTooltip()
257 return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
261 OSPopup *Win32Factory::createOSPopup()
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() )
270 msg_Err( getIntf(), "no window has been created before the popup!" );
274 return new Win32Popup( getIntf(), m_windowMap.begin()->first );
278 int Win32Factory::getScreenWidth() const
280 return GetSystemMetrics(SM_CXSCREEN);
285 int Win32Factory::getScreenHeight() const
287 return GetSystemMetrics(SM_CYSCREEN);
291 Rect Win32Factory::getWorkArea() const
294 SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
295 // Fill a Rect object
296 Rect rect( r.left, r.top, r.right, r.bottom );
301 void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
304 GetCursorPos( &mousePos );
310 void Win32Factory::changeCursor( CursorType_t type ) const
335 HCURSOR hCurs = LoadCursor( NULL, id );
340 void Win32Factory::rmDir( const string &rPath )
342 WIN32_FIND_DATA find;
344 string findFiles = rPath + "\\*";
345 HANDLE handle = FindFirstFile( findFiles.c_str(), &find );
347 while( handle != INVALID_HANDLE_VALUE )
349 // If file is neither "." nor ".."
350 if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
353 file = rPath + "\\" + (string)find.cFileName;
355 // If file is a directory, delete it recursively
356 if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
360 // Else, it is a file so simply delete it
363 DeleteFile( file.c_str() );
367 // If no more file in directory, exit while
368 if( !FindNextFile( handle, &find ) )
372 // Now directory is empty so can be removed
374 RemoveDirectory( rPath.c_str() );