]> git.sesse.net Git - vlc/blob - modules/gui/skins/win32/win32_theme.cpp
34d69703a978549a6e39236d95c432c867a2ce64
[vlc] / modules / gui / skins / win32 / win32_theme.cpp
1 /*****************************************************************************
2  * win32_theme.cpp: Win32 implementation of the Theme class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: win32_theme.cpp,v 1.9 2003/06/22 12:46:49 asmax Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8  *          Emmanuel Puig    <karibu@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,
23  * USA.
24  *****************************************************************************/
25
26 #ifdef WIN32
27
28 #ifdef _MSC_VER
29 #   define _WIN32_WINNT 0x0500
30 #endif
31
32 //--- WIN32 -----------------------------------------------------------------
33 #include <windows.h>
34
35 //--- VLC -------------------------------------------------------------------
36 #include <vlc/intf.h>
37
38 //--- SKIN ------------------------------------------------------------------
39 #include "../os_api.h"
40 #include "../src/banks.h"
41 #include "../src/window.h"
42 #include "../os_window.h"
43 #include "../src/event.h"
44 #include "../os_event.h"
45 #include "../src/theme.h"
46 #include "../os_theme.h"
47 #include "../src/vlcproc.h"
48 #include "../src/skin_common.h"
49
50
51 //---------------------------------------------------------------------------
52 void SkinManage( intf_thread_t *p_intf );
53
54
55
56 //---------------------------------------------------------------------------
57 // Win32 interface
58 //---------------------------------------------------------------------------
59 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
60 {
61     // Get pointer to thread info
62     intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
63         GWLP_USERDATA );
64
65     // If doesn't exist, treat windows message normally
66     if( p_intf == NULL )
67         return DefWindowProc( hwnd, uMsg, wParam, lParam );
68
69     // Create event to dispatch in windows
70     Event *evt = (Event *)new OSEvent( p_intf, hwnd, uMsg, wParam, lParam );
71
72
73     // Find window matching with hwnd
74     list<SkinWindow *>::const_iterator win;
75     for( win = p_intf->p_sys->p_theme->WindowList.begin();
76          win != p_intf->p_sys->p_theme->WindowList.end(); win++ )
77     {
78         // If it is the correct window
79         if( hwnd == ( (Win32Window *)(*win) )->GetHandle() )
80         {
81             // Send event and check if processed
82             if( (*win)->ProcessEvent( evt ) )
83             {
84                 delete (OSEvent *)evt;
85                 return 0;
86             }
87             else
88             {
89                 break;
90             }
91         }
92     }
93     delete (OSEvent *)evt;
94
95
96     // If Window is parent window
97     if( hwnd == ( (Win32Theme *)p_intf->p_sys->p_theme )->GetParentWindow() )
98     {
99         if( uMsg == WM_SYSCOMMAND )
100         {
101             if( (Event *)wParam != NULL )
102                 ( (Event *)wParam )->SendEvent();
103             return 0;
104         }
105         else if( uMsg == WM_RBUTTONDOWN && wParam == 42 &&
106                  lParam == WM_RBUTTONDOWN )
107         {
108             int x, y;
109             OSAPI_GetMousePos( x, y );
110             TrackPopupMenu(
111                 ( (Win32Theme *)p_intf->p_sys->p_theme )->GetSysMenu(),
112                 0, x, y, 0, hwnd, NULL );
113         }
114     }
115
116
117     // If closing parent window
118     if( uMsg == WM_CLOSE )
119     {
120         OSAPI_PostMessage( NULL, VLC_HIDE, VLC_QUIT, 0 );
121         return 0;
122     }
123
124     // If hwnd does not match any window or message not processed
125     return DefWindowProc( hwnd, uMsg, wParam, lParam );
126 }
127 //---------------------------------------------------------------------------
128
129
130
131
132 //---------------------------------------------------------------------------
133 // THEME
134 //---------------------------------------------------------------------------
135 Win32Theme::Win32Theme( intf_thread_t *_p_intf ) : Theme( _p_intf )
136 {
137     // Get instance handle
138     hinst = GetModuleHandle( NULL );
139
140     // Create window class
141     WNDCLASS SkinWindow;
142
143     SkinWindow.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
144     SkinWindow.lpfnWndProc = (WNDPROC) Win32Proc;
145     SkinWindow.lpszClassName = "SkinWindow";
146     SkinWindow.lpszMenuName = NULL;
147     SkinWindow.cbClsExtra = 0;
148     SkinWindow.cbWndExtra = 0;
149     SkinWindow.hbrBackground = HBRUSH (COLOR_WINDOW);
150     SkinWindow.hCursor = LoadCursor( NULL , IDC_ARROW );
151     SkinWindow.hIcon = LoadIcon( hinst, "VLC_ICON" );
152     SkinWindow.hInstance = hinst;
153
154     if( !RegisterClass( &SkinWindow ) )
155     {
156         WNDCLASS wndclass;
157
158         // Check why it failed. If it's because the class already exists
159         // then fine, otherwise return with an error.
160         if( !GetClassInfo( hinst, "SkinWindow", &wndclass ) )
161         {
162             msg_Err( p_intf, "Cannot register window class" );
163             return;
164         }
165     }
166
167     //Initialize value
168     ParentWindow = NULL;
169
170 }
171 //---------------------------------------------------------------------------
172 Win32Theme::~Win32Theme()
173 {
174     // Unregister the window class if needed
175     WNDCLASS wndclass;
176     if( GetClassInfo( hinst, "SkinWindow", &wndclass ) )
177     {
178         UnregisterClass( "SkinWindow", hinst );
179     }
180     if( GetClassInfo( hinst, "ParentWindow", &wndclass ) )
181     {
182         UnregisterClass( "ParentWindow", hinst );
183     }
184
185     // Delete tray icon if exists
186     if( ShowInTray )
187     {
188         Shell_NotifyIcon( NIM_DELETE, &TrayIcon );
189     }
190
191     // Destroy parent window
192     if( ParentWindow )
193     {
194         DestroyWindow( ParentWindow );
195     }
196 }
197 //---------------------------------------------------------------------------
198 void Win32Theme::OnLoadTheme()
199 {
200     // Create window class
201     WNDCLASS ParentClass;
202     ParentClass.style = CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS;
203     ParentClass.lpfnWndProc = (WNDPROC) Win32Proc;
204     ParentClass.lpszClassName = "ParentWindow";
205     ParentClass.lpszMenuName = NULL;
206     ParentClass.cbClsExtra = 0;
207     ParentClass.cbWndExtra = 0;
208     ParentClass.hbrBackground = HBRUSH (COLOR_WINDOW);
209     ParentClass.hCursor = LoadCursor( NULL , IDC_ARROW );
210     ParentClass.hIcon = LoadIcon( hinst, "VLC_ICON" );
211     ParentClass.hInstance = hinst;
212
213     // register class and check it
214     if( !RegisterClass( &ParentClass ) )
215     {
216         WNDCLASS wndclass;
217
218         // Check why it failed. If it's because the class already exists
219         // then fine, otherwise return with an error.
220         if( !GetClassInfo( hinst, "ParentWindow", &wndclass ) )
221         {
222             msg_Err( p_intf, "Cannot register window class" );
223             return;
224         }
225     }
226
227     // Create Window
228     ParentWindow = CreateWindowEx( WS_EX_TOOLWINDOW, "ParentWindow",
229         "VLC Media Player", WS_SYSMENU, 0, 0, 0, 0, 0, 0, hinst, NULL );
230
231     // We do it this way otherwise CreateWindowEx will fail
232     // if WS_EX_LAYERED is not supported
233     SetWindowLongPtr( ParentWindow, GWL_EXSTYLE, GetWindowLong( ParentWindow,
234                       GWL_EXSTYLE ) | WS_EX_LAYERED );
235
236     // Store with it a pointer to the interface thread
237     SetWindowLongPtr( ParentWindow, GWLP_USERDATA, (LONG_PTR)p_intf );
238     ShowWindow( ParentWindow, SW_SHOW );
239
240     // System tray icon
241     TrayIcon.cbSize = sizeof( PNOTIFYICONDATA );
242     TrayIcon.hWnd = ParentWindow;
243     TrayIcon.uID = 42;
244     TrayIcon.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
245     TrayIcon.uCallbackMessage = WM_RBUTTONDOWN;
246     TrayIcon.hIcon = LoadIcon( hinst, "VLC_ICON" );
247     strcpy( TrayIcon.szTip, "VLC Media Player" );
248
249     // Remove default entries from system menu popup
250     SysMenu = GetSystemMenu( ParentWindow, false );
251     RemoveMenu( SysMenu, SC_RESTORE,  MF_BYCOMMAND );
252     RemoveMenu( SysMenu, SC_MOVE,     MF_BYCOMMAND );
253     RemoveMenu( SysMenu, SC_SIZE,     MF_BYCOMMAND );
254     RemoveMenu( SysMenu, SC_MINIMIZE, MF_BYCOMMAND );
255     RemoveMenu( SysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
256     RemoveMenu( SysMenu, SC_CLOSE,    MF_BYCOMMAND );
257     RemoveMenu( SysMenu, 0,           MF_BYPOSITION );
258
259     // The create menu
260     CreateSystemMenu();
261
262 }
263 //---------------------------------------------------------------------------
264 void Win32Theme::AddSystemMenu( string name, Event *event )
265 {
266     if( name == "SEPARATOR" )
267     {
268         AppendMenu( SysMenu, MF_SEPARATOR, 0, NULL );
269     }
270     else
271     {
272         AppendMenu( SysMenu, MF_STRING, (unsigned int)event,
273                     (char *)name.c_str() );
274     }
275 }
276 //---------------------------------------------------------------------------
277 void Win32Theme::ChangeClientWindowName( string name )
278 {
279     SetWindowText( ParentWindow, name.c_str() );
280 }
281 //---------------------------------------------------------------------------
282 void Win32Theme::AddWindow( string name, int x, int y, bool visible,
283     int fadetime, int alpha, int movealpha, bool dragdrop )
284 {
285     HWND hwnd;
286
287     hwnd = CreateWindowEx( WS_EX_TOOLWINDOW,
288         "SkinWindow", name.c_str(), WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
289         0, 0, ParentWindow, 0, hinst, NULL );
290
291     if( !hwnd )
292     {
293         msg_Err( p_intf, "CreateWindow failed" );
294         return;
295     }
296
297     // We do it this way otherwise CreateWindowEx will fail
298     // if WS_EX_LAYERED is not supported
299     SetWindowLongPtr( hwnd, GWL_EXSTYLE,
300                       GetWindowLong( hwnd, GWL_EXSTYLE ) | WS_EX_LAYERED );
301
302     SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_intf );
303
304     WindowList.push_back( (SkinWindow *)new OSWindow( p_intf, hwnd, x, y,
305         visible, fadetime, alpha, movealpha, dragdrop ) ) ;
306 }
307 //---------------------------------------------------------------------------
308 void Win32Theme::ChangeTray()
309 {
310     if( ShowInTray )
311     {
312         Shell_NotifyIcon( NIM_DELETE, &TrayIcon );
313         ShowInTray = false;
314     }
315     else
316     {
317         Shell_NotifyIcon( NIM_ADD, &TrayIcon );
318         ShowInTray = true;
319     }
320 }
321 //---------------------------------------------------------------------------
322 void Win32Theme::ChangeTaskbar()
323 {
324     if( ShowInTaskbar )
325     {
326         ShowWindow( ParentWindow, SW_HIDE );
327         SetWindowLongPtr( ParentWindow, GWL_EXSTYLE,
328                           WS_EX_LAYERED|WS_EX_TOOLWINDOW );
329         ShowWindow( ParentWindow, SW_SHOW );
330         ShowInTaskbar = false;
331     }
332     else
333     {
334         ShowWindow( ParentWindow, SW_HIDE );
335         SetWindowLongPtr( ParentWindow, GWL_EXSTYLE,
336                           WS_EX_LAYERED|WS_EX_APPWINDOW );
337         ShowWindow( ParentWindow, SW_SHOW );
338         ShowInTaskbar = true;
339     }
340 }
341 //---------------------------------------------------------------------------
342
343 #endif