OSDN Git Service

#34026 動画再生時にレーン表示が消えていた問題を修正。
[dtxmania/dtxmania.git] / FDK17プロジェクト / コード / 01.フレームワーク / Core / GameWindow.cs
1 /*\r
2 * Copyright (c) 2007-2009 SlimDX Group\r
3\r
4 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
5 * of this software and associated documentation files (the "Software"), to deal\r
6 * in the Software without restriction, including without limitation the rights\r
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
8 * copies of the Software, and to permit persons to whom the Software is\r
9 * furnished to do so, subject to the following conditions:\r
10\r
11 * The above copyright notice and this permission notice shall be included in\r
12 * all copies or substantial portions of the Software.\r
13\r
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
20 * THE SOFTWARE.\r
21 */\r
22 using System;\r
23 using System.ComponentModel;\r
24 using System.Drawing;\r
25 using System.IO;\r
26 using System.Reflection;\r
27 using System.Security.Permissions;\r
28 using System.Windows.Forms;\r
29 using System.Runtime.InteropServices;\r
30 using System.Diagnostics;\r
31 using SampleFramework.Properties;\r
32 \r
33 namespace SampleFramework\r
34 {\r
35     /// <summary>\r
36     /// Implements a specialized window for games and rendering.\r
37     /// </summary>\r
38     public class GameWindow : Form\r
39     {\r
40         const int DefaultWidth = 800;\r
41         const int DefaultHeight = 600;\r
42         const string DefaultTitle = "Game";\r
43 \r
44         Size cachedSize;\r
45         bool minimized;\r
46         bool maximized;\r
47         bool inSizeMove;\r
48 \r
49         /// <summary>\r
50         /// Occurs when the application is suspended.\r
51         /// </summary>\r
52         public event EventHandler Suspend;\r
53 \r
54         /// <summary>\r
55         /// Occurs when the application is resumed.\r
56         /// </summary>\r
57         public event EventHandler Resume;\r
58 \r
59         /// <summary>\r
60         /// Occurs when the user resizes the window.\r
61         /// </summary>\r
62         public event EventHandler UserResized;\r
63 \r
64         /// <summary>\r
65         /// Occurs when the screen on which the window resides is changed.\r
66         /// </summary>\r
67         public event EventHandler ScreenChanged;\r
68 \r
69         /// <summary>\r
70         /// Occurs when the application is activated.\r
71         /// </summary>\r
72         public event EventHandler ApplicationActivated;\r
73 \r
74         /// <summary>\r
75         /// Occurs when the application is deactivated.\r
76         /// </summary>\r
77         public event EventHandler ApplicationDeactivated;\r
78 \r
79         /// <summary>\r
80         /// Occurs when the system is suspended.\r
81         /// </summary>\r
82         public event EventHandler SystemSuspend;\r
83 \r
84         /// <summary>\r
85         /// Occurs when the system is resumed.\r
86         /// </summary>\r
87         public event EventHandler SystemResume;\r
88 \r
89                 /// <summary>\r
90         /// Occurs when a screen saver is about to be activated.\r
91         /// </summary>\r
92         public event CancelEventHandler Screensaver;\r
93 \r
94                 /// <summary>\r
95         /// Gets a value indicating whether this instance is minimized.\r
96         /// </summary>\r
97         /// <value>\r
98         ///     <c>true</c> if this instance is minimized; otherwise, <c>false</c>.\r
99         /// </value>\r
100         public bool IsMinimized\r
101         {\r
102             get { return minimized; }\r
103         }\r
104 \r
105         /// <summary>\r
106         /// Gets a value indicating whether this instance is maximized.\r
107         /// </summary>\r
108         /// <value>\r
109         ///     <c>true</c> if this instance is maximized; otherwise, <c>false</c>.\r
110         /// </value>\r
111         public bool IsMaximized\r
112         {\r
113             get { return maximized; }\r
114         }\r
115 \r
116                 /// <summary>\r
117                 /// Gets or sets a value indicating whether System Menu is enabled.\r
118                 /// </summary>\r
119                 /// <value><c>true</c> if System Menu is enabled; otherwise, <c>false</c>.</value>\r
120                 public bool EnableSystemMenu                    // #28200 2012.5.1 yyagi\r
121                 {\r
122                         get;\r
123                         set;\r
124                 }\r
125                 public string strMessage                                // #28821 2014.1.23 yyagi\r
126                 {\r
127                         get;\r
128                         private set;\r
129                 }\r
130                 public bool IsReceivedMessage\r
131                 {\r
132                         get;\r
133                         set;\r
134                 }\r
135 \r
136                 private Screen m_Screen;\r
137         /// <summary>\r
138         /// Gets the screen on which the window resides.\r
139         /// </summary>\r
140         /// <value>The screen.</value>\r
141         public Screen Screen\r
142         {\r
143                         get { return m_Screen; }\r
144                         private set { m_Screen = value; }\r
145         }\r
146 \r
147         /// <summary>\r
148         /// Initializes a new instance of the <see cref="GameWindow"/> class.\r
149         /// </summary>\r
150         public GameWindow()\r
151         {\r
152             MinimumSize = new Size(200, 200);\r
153 \r
154             Screen = ScreenFromHandle(Handle);\r
155 \r
156             //Icon = GetDefaultIcon();\r
157             Text = GetDefaultTitle();\r
158                         strMessage = "";\r
159         }\r
160 \r
161         /// <summary>\r
162         /// Raises the <see cref="E:Suspend"/> event.\r
163         /// </summary>\r
164         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
165         protected virtual void OnSuspend(EventArgs e)\r
166         {\r
167             if (Suspend != null)\r
168                 Suspend(this, e);\r
169         }\r
170 \r
171         /// <summary>\r
172         /// Raises the <see cref="E:Resume"/> event.\r
173         /// </summary>\r
174         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
175         protected virtual void OnResume(EventArgs e)\r
176         {\r
177             if (Resume != null)\r
178                 Resume(this, e);\r
179         }\r
180 \r
181         /// <summary>\r
182         /// Raises the <see cref="E:UserResized"/> event.\r
183         /// </summary>\r
184         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
185         protected virtual void OnUserResized(EventArgs e)\r
186         {\r
187             if (UserResized != null)\r
188                 UserResized(this, e);\r
189         }\r
190 \r
191         /// <summary>\r
192         /// Raises the <see cref="E:ScreenChanged"/> event.\r
193         /// </summary>\r
194         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
195         protected virtual void OnScreenChanged(EventArgs e)\r
196         {\r
197             if (ScreenChanged != null)\r
198                 ScreenChanged(this, e);\r
199         }\r
200 \r
201         /// <summary>\r
202         /// Raises the <see cref="E:ApplicationActivated"/> event.\r
203         /// </summary>\r
204         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
205         protected virtual void OnApplicationActivated(EventArgs e)\r
206         {\r
207             if (ApplicationActivated != null)\r
208                 ApplicationActivated(this, e);\r
209         }\r
210 \r
211         /// <summary>\r
212         /// Raises the <see cref="E:ApplicationDeactivated"/> event.\r
213         /// </summary>\r
214         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
215         protected virtual void OnApplicationDeactivated(EventArgs e)\r
216         {\r
217             if (ApplicationDeactivated != null)\r
218                 ApplicationDeactivated(this, e);\r
219         }\r
220 \r
221         /// <summary>\r
222         /// Raises the <see cref="E:SystemSuspend"/> event.\r
223         /// </summary>\r
224         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
225         protected virtual void OnSystemSuspend(EventArgs e)\r
226         {\r
227             if (SystemSuspend != null)\r
228                 SystemSuspend(this, e);\r
229         }\r
230 \r
231         /// <summary>\r
232         /// Raises the <see cref="E:SystemResume"/> event.\r
233         /// </summary>\r
234         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
235         protected virtual void OnSystemResume(EventArgs e)\r
236         {\r
237             if (SystemResume != null)\r
238                 SystemResume(this, e);\r
239         }\r
240 \r
241         /// <summary>\r
242         /// Raises the <see cref="E:Screensaver"/> event.\r
243         /// </summary>\r
244         /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>\r
245         protected virtual void OnScreensaver(CancelEventArgs e)\r
246         {\r
247             if (Screensaver != null)\r
248                 Screensaver(this, e);\r
249         }\r
250 \r
251         /// <summary>\r
252         /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.\r
253         /// </summary>\r
254         /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>\r
255         protected override void OnLoad(EventArgs e)\r
256         {\r
257             base.OnLoad(e);\r
258 \r
259             cachedSize = Size;\r
260         }\r
261 \r
262         /// <summary>\r
263         /// Raises the <see cref="E:System.Windows.Forms.Form.ResizeBegin"/> event.\r
264         /// </summary>\r
265         /// <param name="e">A <see cref="T:System.EventArgs"/> that contains the event data.</param>\r
266         protected override void OnResizeBegin(EventArgs e)\r
267         {\r
268             base.OnResizeBegin(e);\r
269 \r
270             // suspend any processing until we are done being minimized\r
271             inSizeMove = true;\r
272             cachedSize = Size;\r
273             OnSuspend(EventArgs.Empty);\r
274         }\r
275 \r
276         /// <summary>\r
277         /// Raises the <see cref="E:System.Windows.Forms.Form.ResizeEnd"/> event.\r
278         /// </summary>\r
279         /// <param name="e">A <see cref="T:System.EventArgs"/> that contains the event data.</param>\r
280         protected override void OnResizeEnd(EventArgs e)\r
281         {\r
282             base.OnResizeEnd(e);\r
283 \r
284             // check for screen and size changes\r
285             OnUserResized(EventArgs.Empty);\r
286             UpdateScreen();\r
287             inSizeMove = false;\r
288 \r
289             // resume application processing\r
290             OnResume(EventArgs.Empty);\r
291                 }\r
292 \r
293 \r
294                 #region #23510 2010.11.14 yyagi add: 縦横比固定でのウインドウサイズ変更 定数定義 from http://www.vcskicks.com/maintain-aspect-ratio.php\r
295                 //double so division keeps decimal points\r
296                 const double widthRatio = SampleFramework.GameWindowSize.Width;\r
297                 const double heightRatio = SampleFramework.GameWindowSize.Height;\r
298                 const int WM_SIZING = 0x214;\r
299                 const int WMSZ_LEFT = 1;\r
300                 const int WMSZ_RIGHT = 2;\r
301                 const int WMSZ_TOP = 3;\r
302                 const int WMSZ_TOPLEFT = 4;\r
303                 const int WMSZ_TOPRIGHT = 5;\r
304                 const int WMSZ_BOTTOM = 6;\r
305                 const int WMSZ_BOTTOMLEFT = 7;\r
306                 const int WMSZ_BOTTOMRIGHT = 8;\r
307 \r
308                 public struct RECT\r
309                 {\r
310                         public int Left;\r
311                         public int Top;\r
312                         public int Right;\r
313                         public int Bottom;\r
314                 }\r
315                 #endregion\r
316 \r
317 \r
318 \r
319                 /// <summary>\r
320         /// Handles raw window messages.\r
321         /// </summary>\r
322         /// <param name="m">The raw message.</param>\r
323         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]\r
324         protected override void WndProc(ref Message m)\r
325         {\r
326                         if (m.Msg == WindowConstants.WM_SIZE)\r
327             {\r
328                 if (m.WParam == WindowConstants.SIZE_MINIMIZED)\r
329                 {\r
330                     minimized = true;\r
331                     maximized = false;\r
332 \r
333                     OnSuspend(EventArgs.Empty);\r
334                 }\r
335                 else\r
336                 {\r
337                     Rectangle client = NativeMethods.GetClientRectangle(m.HWnd);\r
338                     if (client.Height == 0)\r
339                     {\r
340                         // rapidly clicking the task bar to minimize and restore a window\r
341                         // can cause a WM_SIZE message with SIZE_RESTORED when \r
342                         // the window has actually become minimized due to rapid change\r
343                         // so just ignore this message\r
344                     }\r
345                     else if (m.WParam == WindowConstants.SIZE_MAXIMIZED)\r
346                     {\r
347                         if (minimized)\r
348                             OnResume(EventArgs.Empty);\r
349 \r
350                         minimized = false;\r
351                         maximized = true;\r
352 \r
353                         OnUserResized(EventArgs.Empty);\r
354                         UpdateScreen();\r
355                     }\r
356                     else if (m.WParam == WindowConstants.SIZE_RESTORED)\r
357                     {\r
358                         if (minimized)\r
359                             OnResume(EventArgs.Empty);\r
360 \r
361                         minimized = false;\r
362                         maximized = false;\r
363 \r
364                         if (!inSizeMove && Size != cachedSize)\r
365                         {\r
366                             OnUserResized(EventArgs.Empty);\r
367                             UpdateScreen();\r
368                             cachedSize = Size;\r
369                         }\r
370                     }\r
371                 }\r
372             }\r
373             else if (m.Msg == WindowConstants.WM_ACTIVATEAPP)\r
374             {\r
375                 if (m.WParam != IntPtr.Zero)\r
376                     OnApplicationActivated(EventArgs.Empty);\r
377                 else\r
378                     OnApplicationDeactivated(EventArgs.Empty);\r
379             }\r
380             else if (m.Msg == WindowConstants.WM_POWERBROADCAST)\r
381             {\r
382                 if (m.WParam == WindowConstants.PBT_APMQUERYSUSPEND)\r
383                 {\r
384                     OnSystemSuspend(EventArgs.Empty);\r
385                     m.Result = (IntPtr)1;\r
386                     return;\r
387                 }\r
388                 else if (m.WParam == WindowConstants.PBT_APMRESUMESUSPEND)\r
389                 {\r
390                     OnSystemResume(EventArgs.Empty);\r
391                     m.Result = (IntPtr)1;\r
392                     return;\r
393                 }\r
394             }\r
395             else if (m.Msg == WindowConstants.WM_SYSCOMMAND)\r
396             {\r
397                 long wparam = m.WParam.ToInt64() & 0xFFF0;\r
398                 if (wparam == WindowConstants.SC_MONITORPOWER || wparam == WindowConstants.SC_SCREENSAVE)\r
399                 {\r
400                     CancelEventArgs e = new CancelEventArgs();\r
401                     OnScreensaver(e);\r
402                     if (e.Cancel)\r
403                     {\r
404                         m.Result = IntPtr.Zero;\r
405                         return;\r
406                     }\r
407                                 }\r
408                                 #region #28200 2012.5.1 yyagi: Disable system menu\r
409                                 if ( ( m.WParam.ToInt32() & 0xFFFF ) == 0xF100 && !EnableSystemMenu )   // SC_KEYMENU\r
410                                 {\r
411                                         m.Result = IntPtr.Zero;\r
412                                         return;\r
413                                 }\r
414                                 #endregion\r
415                                 #region #23510 2010.11.13 yyagi: reset to 640x480\r
416                                 if ((m.WParam.ToInt32() & 0xFFFF) == MENU_VIEW)         \r
417                                 {\r
418                                         base.ClientSize = new Size(SampleFramework.GameWindowSize.Width, SampleFramework.GameWindowSize.Height);\r
419                                         this.OnResizeEnd(new EventArgs());              // #23510 2010.11.20 yyagi: to set window size to Config.ini\r
420                                 }\r
421                                 else\r
422                                 if ((m.WParam.ToInt32() & 0xFFFF) == MENU_VIEW - 1)             \r
423                                 {\r
424                                         base.ClientSize = new Size( 1280, 720 );\r
425                                         this.OnResizeEnd(new EventArgs());              // #23510 2010.11.20 yyagi: to set window size to Config.ini\r
426                                 }\r
427                                 else\r
428                                 if ((m.WParam.ToInt32() & 0xFFFF) == MENU_VIEW - 2)             \r
429                                 {\r
430                                         base.ClientSize = new Size( 640, 480 );\r
431                                         this.OnResizeEnd(new EventArgs());              // #23510 2010.11.20 yyagi: to set window size to Config.ini\r
432                                 }\r
433                                 #endregion\r
434                         }\r
435                         #region #28821 2014.1.23 yyagi (WM_COPYDATA)\r
436                         else if ( m.Msg == WindowConstants.WM_COPYDATA )\r
437                         {\r
438 //Trace.WriteLine( "FDK;msg received" );\r
439                                 COPYDATASTRUCT cds = (COPYDATASTRUCT) Marshal.PtrToStructure( m.LParam, typeof( COPYDATASTRUCT ) );\r
440                                 strMessage = Marshal.PtrToStringUni( cds.lpData );\r
441                                 IsReceivedMessage = true;\r
442 //Trace.WriteLine( "FDK;msg=" + strMessage + ", len=" + strMessage.Length + ", truelen=" + cds.cbData );\r
443                         }\r
444                         #endregion\r
445                         #region #23510 2010.11.16 yyagi add: 縦横比固定でのウインドウサイズ変更 from http://d.hatena.ne.jp/iselix/20080917/1221666614 http://hp.vector.co.jp/authors/VA016117/sizing.html\r
446                         else if ( m.Msg == WM_SIZING )\r
447                         {\r
448                                 RECT rc = (RECT) Marshal.PtrToStructure( m.LParam, typeof( RECT ) );\r
449                                 int w = rc.Right - rc.Left - ( Size.Width - ClientSize.Width );\r
450                                 int h = rc.Bottom - rc.Top - ( Size.Height - ClientSize.Height );\r
451                                 int dw = (int) ( h * widthRatio / heightRatio + 0.5 ) - w;\r
452                                 int dh = (int) ( w / ( widthRatio / heightRatio ) + 0.5 ) - h;\r
453 \r
454                                 switch ( m.WParam.ToInt32() )\r
455                                 {\r
456                                         case WMSZ_LEFT:\r
457                                         case WMSZ_RIGHT:\r
458                                                 rc.Bottom += dh;\r
459                                                 break;\r
460                                         case WMSZ_TOP:\r
461                                         case WMSZ_BOTTOM:\r
462                                                 rc.Right += dw;\r
463                                                 break;\r
464                                         case WMSZ_BOTTOMRIGHT:\r
465                                                 if ( dw > 0 )\r
466                                                 {\r
467                                                         rc.Right += dw;\r
468                                                 }\r
469                                                 else\r
470                                                 {\r
471                                                         rc.Bottom += dh;\r
472                                                 }\r
473                                                 break;\r
474                                         case WMSZ_TOPLEFT:\r
475                                                 if ( dw > 0 )\r
476                                                 {\r
477                                                         rc.Left -= dw;\r
478                                                 }\r
479                                                 else\r
480                                                 {\r
481                                                         rc.Top -= dh;\r
482                                                 }\r
483                                                 break;\r
484                                         case WMSZ_TOPRIGHT:\r
485                                                 if ( dw > 0 )\r
486                                                 {\r
487                                                         rc.Right += dw;\r
488                                                 }\r
489                                                 else\r
490                                                 {\r
491                                                         rc.Top -= dh;\r
492                                                 }\r
493                                                 break;\r
494                                         case WMSZ_BOTTOMLEFT:\r
495                                                 if ( dw > 0 )\r
496                                                 {\r
497                                                         rc.Left -= dw;\r
498                                                 }\r
499                                                 else\r
500                                                 {\r
501                                                         rc.Bottom += dh;\r
502                                                 }\r
503                                                 break;\r
504                                         case 9:         // #32383 2013.11.2 yyagi; exitting maximized window by using Aero snap\r
505                                                 break;\r
506                                         default:\r
507                                                 throw new ArgumentOutOfRangeException( "value", "Illegal WM_SIZING value." );\r
508                                 }\r
509                                 Marshal.StructureToPtr( rc, m.LParam, true );\r
510                         }\r
511                         #endregion\r
512 \r
513 \r
514                         base.WndProc(ref m);\r
515         }\r
516 \r
517         void UpdateScreen()\r
518         {\r
519             Screen current = Screen.FromHandle(Handle);\r
520             if (Screen == null || Screen.DeviceName != current.DeviceName)\r
521             {\r
522                 Screen = current;\r
523                 if (Screen != null)\r
524                     OnScreenChanged(EventArgs.Empty);\r
525             }\r
526         }\r
527 \r
528         static Screen ScreenFromHandle(IntPtr windowHandle)\r
529         {\r
530             Rectangle rectangle = NativeMethods.GetWindowRectangle(windowHandle);\r
531 \r
532             Screen bestScreen = null;\r
533             int mostArea = 0;\r
534             foreach (Screen screen in Screen.AllScreens)\r
535             {\r
536                 Rectangle r = Rectangle.Intersect(rectangle, screen.Bounds);\r
537                 int area = r.Width * r.Height;\r
538 \r
539                 if (area > mostArea)\r
540                 {\r
541                     mostArea = area;\r
542                     bestScreen = screen;\r
543                 }\r
544             }\r
545 \r
546             if (bestScreen == null)\r
547                 bestScreen = Screen.PrimaryScreen;\r
548             return bestScreen;\r
549         }\r
550 \r
551         static string GetAssemblyTitle(Assembly assembly)\r
552         {\r
553             if (assembly == null)\r
554                 return null;\r
555 \r
556             AssemblyTitleAttribute[] customAttributes = (AssemblyTitleAttribute[])assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), true);\r
557             if (customAttributes != null && customAttributes.Length > 0)\r
558                 return customAttributes[0].Title;\r
559 \r
560             return null;\r
561         }\r
562 \r
563         static string GetDefaultTitle()\r
564         {\r
565             string assemblyTitle = GetAssemblyTitle(Assembly.GetEntryAssembly());\r
566             if (!string.IsNullOrEmpty(assemblyTitle))\r
567                 return assemblyTitle;\r
568 \r
569             try\r
570             {\r
571                 Uri uri = new Uri(Application.ExecutablePath);\r
572                 return Path.GetFileNameWithoutExtension(uri.LocalPath);\r
573             }\r
574             catch (ArgumentNullException)\r
575             {\r
576                 // swallow the exception\r
577             }\r
578             catch (UriFormatException)\r
579             {\r
580                 // swallow the exception\r
581             }\r
582 \r
583             return DefaultTitle;\r
584         }\r
585 \r
586         static Icon GetDefaultIcon()\r
587         {\r
588             return (Icon)Resources.sdx_icon_black.Clone();\r
589                 }\r
590 \r
591                 #region システムメニューに"1920x1080", "1280x720", "640x480" を追加 #23510 2010.11.13 yyagi add: to set "1920x1020","1280x720","640x480" menu in systemmenu. See also http://cs2ch.blog123.fc2.com/blog-entry-80.html\r
592                 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]\r
593                 private struct MENUITEMINFO\r
594                 {\r
595                         public uint cbSize;\r
596                         public uint fMask;\r
597                         public uint fType;\r
598                         public uint fState;\r
599                         public uint wID;\r
600                         public IntPtr hSubMenu;\r
601                         public IntPtr hbmpChecked;\r
602                         public IntPtr hbmpUnchecked;\r
603                         public IntPtr dwItemData;\r
604                         public string dwTypeData;\r
605                         public uint cch;\r
606                         public IntPtr hbmpItem;\r
607                 }\r
608 \r
609                 [DllImport("user32", ExactSpelling = true)]\r
610                 private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);\r
611                 [DllImport("user32", CharSet = CharSet.Auto)]\r
612                 private static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii);\r
613 \r
614                 private const uint MENU_VIEW = 0x9999;\r
615                 private const uint MFT_SEPARATOR = 0x00000800;\r
616                 private const uint MIIM_FTYPE = 0x00000100;\r
617                 private const uint MIIM_STRING = 0x00000040;\r
618                 private const uint MIIM_ID = 0x00000002;\r
619 \r
620                 protected override void OnCreateControl()\r
621                 {\r
622                         base.OnCreateControl();\r
623 \r
624                         //システムメニューのハンドル取得   \r
625                         IntPtr hSysMenu = GetSystemMenu(this.Handle, false);\r
626 \r
627                         //セパレーターの挿入   \r
628                         MENUITEMINFO item1 = new MENUITEMINFO();\r
629                         item1.cbSize = (uint)Marshal.SizeOf(item1);\r
630                         item1.fMask = MIIM_FTYPE;\r
631                         item1.fType = MFT_SEPARATOR;\r
632                         InsertMenuItem(hSysMenu, 5, true, ref item1);\r
633 \r
634                         //メニュー項目(1920x1080)の挿入   \r
635                         MENUITEMINFO item2 = new MENUITEMINFO();\r
636                         item2.cbSize = (uint)Marshal.SizeOf(item2);\r
637                         item2.fMask = MIIM_STRING | MIIM_ID;\r
638                         item2.wID = MENU_VIEW;\r
639                         item2.dwTypeData = "&" + SampleFramework.GameWindowSize.Width.ToString() + "x" + SampleFramework.GameWindowSize.Height.ToString();\r
640                         InsertMenuItem(hSysMenu, 6, true, ref item2);\r
641 \r
642                         //メニュー項目(1280x720)の挿入   \r
643                         MENUITEMINFO item3 = new MENUITEMINFO();\r
644                         item3.cbSize = (uint) Marshal.SizeOf( item3 );\r
645                         item3.fMask = MIIM_STRING | MIIM_ID;\r
646                         item3.wID = MENU_VIEW - 1;\r
647                         item3.dwTypeData = "&1280x720";\r
648                         InsertMenuItem( hSysMenu, 6, true, ref item3 );\r
649 \r
650                         //メニュー項目(640x480)の挿入   \r
651                         MENUITEMINFO item4 = new MENUITEMINFO();\r
652                         item4.cbSize = (uint) Marshal.SizeOf( item4 );\r
653                         item4.fMask = MIIM_STRING | MIIM_ID;\r
654                         item4.wID = MENU_VIEW - 2;\r
655                         item4.dwTypeData = "&640x480";\r
656                         InsertMenuItem( hSysMenu, 6, true, ref item4 );\r
657                 }   \r
658                 #endregion\r
659         }\r
660 }\r