CESYSGEN 条件文での ‘Component’ 名タスクバーの非表示~Taskman Shell の組込み

タスクバーの非表示(フルスクリーン表示)

2011/08/15 koga

アプリケーションをフルスクリーン表示したい場合、つまり、タスクバーを表示しないで、アプリケーションのウィンドウを全画面に表示したい場合、WinCE 6.0 では、いくつかの方法があります。標準シェル(explorer.exe)を使わずに、カスタムのシェルを組み込んだ OS イメージを作る、というのは、その方法の一つです。しかし、今回は、OS をカスタマイズせず、レジストリ設定や、アプリケーションからの API 呼び出しだけで対応する方法を述べます。

以下では、OS をカスタマイズせずにタスクバーを非表示にする方法を、三通り紹介します。一つは、レジストリ設定を変更することにより、全てのアプリケーションをフルスクリーン表示可能にする方法で、残り二つは、アプリケーションが API 呼び出しを行ってフルスクリーン表示する方法です。では、順に見ていきましょう。

■レジストリ設定による方法
まず最初は、レジストリ設定による方法です。この方法では、タスクバーが最前面(TOPMOST)に表示されないように設定することで、スクリーンと同サイズのウィンドウを表示した際、ウィンドウの下端がタスクバーで隠されてしまうのを防ぎます。具体的には、
 [HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\OnTop]
キーのデフォルト値を dword:0 に設定します。この設定を行うと、CreateWindow() でウィンドウの幅と高さに 0 を指定して、幅と高さにデフォルト値を使う場合や、それから、SystemParametersInfo() に SPI_GETWORKAREA を指定して work area を取得して、work area と同サイズでウィンドウを表示するアプリケーションは、全てフルスクリーン表示となります。たとえば、シェルのエクスプローラーウィンドウ(フォルダウィンドウ)でも、タスクバーが表示されず、フルスクリーン表示されます。シェルのエクスプローラーウィンドウもフルスクリーン表示されると都合がよくない場合は、以下で述べる、API 呼び出しによる方法を使ってみて下さい。

なお、シェルの OnTop というキーに対する説明は、WinCE のリファレンスには記載されておらず、MSDN フォーラムの投稿などでしか見当たりません。たとえば、次のページです:

 http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/a5293f70-0587-4812-b50f-cbfdee9e6d0e

WinCE のリファレンスには、[HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\AutoHide] というキーに関する説明が載っていますが、このキーを設定しても、タスクバーは完全に隠れず、隠れた状態では6ピクセルの高さだけ、画面下端にタスクバーが表示されます:

 http://msdn.microsoft.com/en-US/library/ee501693(v=WinEmbedded.60).aspx (Enabling Slide Animation for the Taskbar)

■AYGShell API による方法
二番目は、AYGShell の API を使う方法です。この方法では、フルスクリーン表示用の API を呼び出したうえで、アプリケーションのウィンドウのサイズを、スクリーンと同サイズにします。ただし、WinCE 6.0 付属の標準シェルでは、フルスクリーン表示用の AYGShell API に対する応答動作の実装に不足があると思われ、追加の API 呼び出しが必要です。

フルスクリーン表示用の AYGShell API は、SHFullScreen() という関数です:

 http://msdn.microsoft.com/en-US/library/ee499392(v=WinEmbedded.60).aspx (SHFullScreen)

上のリファレンスページには、タスクバーを非表示にしてフルスクリーン表示する処理、および、タスクバーを表示してフルスクリーン表示を解除する処理のサンプルコードも記載されています。しかし、WinCE 6.0 付属の標準シェルでは、SHFullScreen() に対する応答動作の実装が、リファレンス記載の仕様とは合っておらず、そのため、上のページ記載のサンプルコードは、期待通りに動作しません(タスクバーが非表示となりません)。SHFullScreen() のリファレンスには、この関数の第二引数に SHFS_HIDETASKBAR を渡した場合、「タスクバーが、z オーダーの底」に移動する、つまり、ウィンドウの重なり位置の最背面に移動すると書かれていますが、WinCE 6.0 付属の標準シェルの実装は、そうなっていないのです。

標準シェルのソースファイルは、%_WINCEROOT%/PUBLIC/shell/oak/hpc/explorer/ 配下にあり、タスクバーのソースファイルは、taskbar/ サブディレクトリに配置されています。そして、SHFullScreen() に対する応答動作は、taskbar,cpp の CTaskBar::TaskBarWndProc() で実装されています。CTaskBar::TaskBarWndProc() の中の switch 文で、SPECIAL_HIDE_MESSAGE と SPECIAL_SHOW_MESSAGE に対する case 節が、当該個所です。ソースを追ってもらえば分かると思いますが、SHFullScreen() の呼び出しによって SPECIAL_HIDE_MESSAGE が送られても、標準シェルのタスクバーの実装(CTaskBar クラス)では、タスクバーがウィンドウメッセージに応答しないようにするだけで(※受け取ったメッセージを、SHFullScreen() の第1引数に渡されたウィンドウに全て転送します)、タスクバーの表示変更は、何も行いません。つまり、リファレンスに書かれている「タスクバーを z オーダーの底」に移動する処理は、行わないのです。

SHFullScreen() の呼び出しに対するタスクバーの動作が、リファレンスに記載された通りではないことへの対応策の一つは、標準シェルの実装を修正することです。しかし、その対応では、OS のカスタマイズが必要であり、アプリケーションだけでは対応できません。アプリケーションだけで対応する場合は、SHFullScreen() の呼び出しの後、SetWindowPos() を使って、アプリケーションのウィンドウを最前面に移動することで解決できます。

SHFullScreen() のリファレンスページに記載されているサンプルコードの場合で言うと、次の対応を追加することにより、タスクバーの非表示/表示切り替えによる、アプリケーションのウィンドウのフルスクリーン表示/解除ができるようになります:

・タスクバーを非表示/アプリケーションのウィンドウをフルスクリーン表示する時
 SHFullScreen() の呼び出しの後に、次の行を追加する:

 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

・タスクバーを表示/アプリケーションのウィンドウのフルスクリーン表示を解除する時
 SHFullScreen() の呼び出しの後に、次の行を追加する:

 SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

■レジストリ設定の動的変更による方法
最後の三番目は、一番目に述べた OnTop キーの値を動的に変更することにより、フルスクリーン表示するアプリケーションの動作中にだけ、タスクバーの最前面表示を行わないようにする、という方法です。この方法は、AYGShell API が OS イメージに組み込まれていない場合に有効です。AYGShell API は、WinCE 6.0 の SKU のうち、最もライセンス価格が安価な “Core”、および “Core Plus” には含まれません。そのため、AYGShell を組込まないコンフィグレーションの OS イメージがデバイスに搭載されている場合があります。

さて、レジストリの [HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\OnTop] キーの値を動的に変更する場合は、単にキー値を変更するだけでは、タスクバーの非表示・表示の切り替え(最前面表示の無効化・有効化の切り替え)を行うことは、できません。レジストリのキー値を変更した際に、タスクバーに通知して、レジストリ設定をロードし直させる必要があるのです。標準シェルのソースを読むと分かりますが、この通知は、WM_WININICHANGE メッセージを使って行うことができます。メッセージのパラメータは、wParam が 0、lParam が 5000 です。

SHFullScreen() のリファレンスページ記載のサンプルコードを真似て書くと、次のようになります。


LRESULT CALLBACK SHFullScreenWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static fFullScreen = FALSE;
    switch (message)
    {
        case WM_KEYDOWN:
        {
            // Toggle between full screen and normal mode when the user presses the space bar.
            if (VK_SPACE == wParam)
            {
                HWND   tbWndH;
                HKEY   keyH;
                DWORD  onTop = (!fFullscreen ? 0 : 1);
                DWORD  dwState;
                RECT   rc;

                if (0 != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                    L"Software\\Microsoft\\Shell\\OnTop",
                    0, KEY_ALL_ACCESS, &keyH))
                {
                    DWORD	disp;

                    if (0 != ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                        L"Software\\Microsoft\\Shell\\OnTop",
                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &keyH, &disp))
                    {
                            break;  // error
                    }
                }
                (void)RegSetValueEx(keyH, L"", 0, REG_DWORD, (LPBYTE)&onTop, sizeof(DWORD));
                (void)RegCloseKey(keyH);

                tbWndH = FindWindow(L"HHTaskBar", NULL);
                if (NULL == windowH)
                {
                    break;  // error
                }
                SendMessage(windowH, WM_WININICHANGE, 0, 5000);

                if (fFullScreen)
                {
                    // resize the main window to the size of the work area.
                    SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);
                    MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
                    fFullScreen = !fFullScreen;
                }
                else
                {
                     // resize the main window to the size of the screen.
                    SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
                    MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
                    fFullScreen = !fFullScreen;
                }
            }
        }
        break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

Entry Filed under: アプリケーション開発

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Categories

Links

Posts by Authors

Recent Posts

Calendar

2011年8月
« 2月   9月 »
 123456
78910111213
14151617181920
21222324252627
28293031  

Posts by Month

Posts by Category

Meta