C++/CLI によるScreen Saver スケルトンコード

Windows Mobile の Today のプラグインを実装しようと思うと、WnProc を実装する必要があり、C#だけでは実装できない。

http://msdn.microsoft.com/en-us/library/ms839442.aspx

に、Creating a Pocket PC Today Screen Plug-in with the .NET Compact Framework という方法も載っているが、これだと共有メモリを使ってHTMLをレンダリングさせる方法なので、かえって見通しが悪そう。これなら、直接C++/CLIで実装して、一部を C#で書いたほうが楽そう。ただ、TodayのプラグインがC++/CLIで実装可能かどうか・・・C++/CLIでも実装可能なら、一部を C# で書くことも可能なので、ちょっと込み入った実装もだいぶ楽になるはず。

少し調べていたら、

http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_01.html

に「いままたC++が熱い!「C++/CLI」として大進化したVisual C++ 2005」の記事があり、C++/CLI によるScreen Saver のサンプルがあったので、試してみた。

結果はWinProc をC++/CLIで動かすことができる。ということは、おそらく Windows Mobile の Today のプラグインも同様に動くと思われると、思ったが、スマートデバイスのプロジェクトテンプレートでは、C++/CLI がサポートされないみたい orz

ピーデー 川俣 晶さんがアップしているコードを VS2008用にちょっと修正したので、とりあえずメモ。

  • コンパイル時の設定に、構成プロパティ→全般に 共通言語ランタイムサポート をセット。
  • 構成プロパティ→リンカ→追加の依存ファイルに scrnsavw.lib comctl32.lib をセット。
  • コンパイルしたイメージを /Sで起動。

#include <stdafx.h>
#include <windows.h>
#include <scrnsave.h>

#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms; 

UINT_PTR wTimer;
WORD wElapse = 1000;
int xText=0, yText=0;

#define ID_TIMER 1

LONG CALLBACK ScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    case WM_CREATE:
      {
        wTimer = SetTimer(hWnd, ID_TIMER, wElapse, NULL);
      }
      break;

    case WM_TIMER:
      {
        HDC hdc = GetDC(hWnd);
        xText = rand() % GetDeviceCaps(hdc,HORZRES);
        yText = rand() % GetDeviceCaps(hdc,VERTRES);
        ReleaseDC(hWnd,hdc);
        InvalidateRect(hWnd,NULL,TRUE);
      }
      break;

    case WM_DESTROY:
      if( wTimer ) KillTimer(hWnd, ID_TIMER);
      break;

    case WM_PAINT:
      {
        PAINTSTRUCT ps;
        HDC hDC = BeginPaint(hWnd, &ps);
{
System::Drawing::
Graphics ^ g = Graphics::FromHdc((IntPtr)hDC);
Font font("MS ゴシック", 160);
SolidBrush brush( Color::Blue);
PointF position( (float)xText, (float)yText );
g->DrawString( "テスト!",  %font,  %brush, position );
}
EndPaint(hWnd, &ps);
      }
      break;

    case WM_ERASEBKGND:
      {
        RECT rc;
        GetClientRect(hWnd,&rc);
        FillRect((HDC)wParam, &rc,
            (HBRUSH)GetStockObject(BLACK_BRUSH));
      }
      return 0L;

    default:
      break;
  }

  return DefScreenSaverProc(hWnd, msg, wParam, lParam);
}

BOOL WINAPI RegisterDialogClasses (HANDLE hInst)
{
  return TRUE;
}

BOOL CALLBACK ScreenSaverConfigureDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  return FALSE;
}