FC2ブログ

まったり開発日誌

embossの工具箱(J2EE Java2 Linux Zaurus C++)

2008年06月

  1. スポンサーサイト(--/--)
  2. 008:システムフォントを使う(06/26)
  3. 007:フォントを変更する(カスタムフォント)(06/25)
  4. 006:文字を表示する(06/24)
  5. 005:MessageBoxを使ってhello,world(06/23)
  6. 004:クロスプラットフォームに対応する(06/22)
  7. 003:ウィンドウを作る(06/20)
  8. 002:Visual Studio 2005の起動(06/18)
  9. 001:Windows Mobile開発環境の構築(06/16)
  10. 参考文献(06/16)

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  1. --/--/--(--) --:--:--|
  2. スポンサー広告

008:システムフォントを使う

自由にフォントが扱えるようになりました。作成するアプリケーションによっては、システムに内蔵されたフォントを使いたい場合も出てくるでしょう。そのような場合には、システムフォントを使用します。

システムフォントはWindows Mobileが標準的に備えているフォントです。標準的に使用するフォントは、環境によらず使えるように、標準フォントとして初めから用意され、様々な場面で標準フォント (デフォルト・フォント) として使用されます。
どのような環境でも同じように表示されるアプリケーションを作るためには、システムフォトを使用するのが良いですね。

システムフォントを取得するにはGetStockObject関数を使用します。

GetStockObject関数はフォント用というわけではなく、定義済み(ストック)のペン、ブラシ、フォント、パレットのいずれかを取得します。

HGDIOBJ GetStockObject(
 int fnObject   
// ストックオブジェクトのタイプ
);

fnObjectのフォント関係の主なオプションには次のようなタイプがあります。

ANSI_FIXED_FONT:Windows の固定幅(モノスペース)システムフォント
ANSI_VAR_FONT:Windows の可変幅(プロポーショナル)システムフォント
DEVICE_DEFAULT_FONT:デバイス依存のフォント
OEM_FIXED_FONT:OEM 文字の固定幅(モノスペース)フォント
SYSTEM_FONT:システムフォントを指定します。これはWindows文字セットに基づくプロポーショナルフォントです。システムフォントは常に利用可能ですが、他のフォントはインストールされている場合のみ利用可能です。
  

上記フォント関係Windows Mobileで使用できるのはSYSTEM_FONTだけです。

戻り値はHGDIOBJです。GDIオブジェクトのハンドルが戻ります(フォントの場合はHFONTです)。

サンプルプログラムを見てみましょう。

// text004.cpp
//
// ストックオブジェクトからシステムフォントを得る

#include <windows.h
>
#include <tchar.h
>
#include <strsafe.h
>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM
);
ATOM InitApp(HINSTANCE
);
HWND InitInstance(HINSTANCE, int
);

WCHAR szClassName[] = _T("text004");
// ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd
)
{
   MSG msg
;
   BOOL bRet
;
   HWND hWnd
;

   if (!InitApp(hInstance
))
       return FALSE
;
   if (!(hWnd = InitInstance(hInstance,nShowCmd
)))
       return FALSE
;
   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
       if (bRet == -1
){
           break
;
       } else
{
           TranslateMessage(&msg
);
           DispatchMessage(&msg
);
       
}
   
}
   return (int)msg.wParam
;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst
)
{
   WNDCLASS wc
;
   wc.style        = CS_HREDRAW|CS_VREDRAW
;
   wc.lpfnWndProc  = WndProc;  
// プロシージャ名
   wc.cbClsExtra   = 0
;
   wc.cbWndExtra   = 0
;
   wc.hInstance    = hInst
;
   wc.hIcon        = NULL;     
// 未サポート
   wc.hCursor      = NULL;     
// 未サポート
   wc.hbrBackground= (HBRUSH) COLOR_WINDOW
;
   wc.lpszMenuName = NULL;     
// 未サポート
   wc.lpszClassName=(LPCTSTR) szClassName
;

   return (RegisterClass(&wc
));
}

// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd
)
{
   HWND hWnd
;

   hWnd = CreateWindow(szClassName,_T("Window Title"),
       WS_CLIPCHILDREN,    
// ウィンドウの種類
       CW_USEDEFAULT,      
// x座標
       CW_USEDEFAULT,      
// y座標
       CW_USEDEFAULT,      
// 幅
       CW_USEDEFAULT,      
// 高さ
       NULL,               
// 親ウィンドウのハンドル。親を作るのでNULL
       NULL,               
// メニューハンドルまたは子ウィンドウID
       hInst,              
// インスタンスハンドル
       NULL
);
   if (!hWnd
)
       return FALSE
;
   ShowWindow(hWnd, nShowCmd
);
   UpdateWindow(hWnd
);
   return hWnd
;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp
)
{
   PAINTSTRUCT ps
;
   HDC hdc
;
   LPTSTR lpszStr= _T("WindowsMobile Win32APIプログラミング"
);
   size_t size;        
// 文字列のサイズを格納する
   StringCchLength(lpszStr,STRSAFE_MAX_CCH,&size);
// 安全な文字列取得
   HGDIOBJ hFont
;
   HGDIOBJ hFontOld
;

   switch (msg
){
       case WM_PAINT
:
           hdc = BeginPaint(hWnd,&ps);     
// 描画処理を開始します。

           hFont = GetStockObject(SYSTEM_FONT);    
// システムフォントを取得する
           hFontOld = SelectObject(hdc,hFont);     
// フォントを指定・現在のフォントを退避
           ExtTextOut(hdc, 0, 20, NULL, NULL, lpszStr, size, NULL
);
           SelectObject(hdc,hFontOld);             
// フォントを元に戻す

           EndPaint(hWnd,&ps
);
           break
;
       case WM_DESTROY
:
           PostQuitMessage(0
);
           break
;
       default
:
           return (DefWindowProc(hWnd, msg, wp, lp
));
   
}
   return 0
;
}

実行結果

今日はここまでです。

スポンサーサイト

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/26(木) 23:52:11|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

007:フォントを変更する(カスタムフォント)

さて画面に文字が書けるようになったら、次はフォントや色を変更してみたくなりますね。
本日は、フォントの変更に挑戦しましょう。

CreateFontがない!
フォント生成サンプルを作成し、さてコンパイルしようとしましたが、CreateFontがなぜかコンパイル通りません。そうです、Windows Mobile には、フォント生成するための関数CreateFontが無いのです。
困った、これではフォントの変更はどうするのだと思いきや、CreateFontIndirect関数が使えるようです。

CreateFontとCreateFontIndirectは両方とも論理フォントを作成する関数です。違いは引数だけです。CreateFontは引数にフォント情報を渡しますが、CreateFontIndirectは引数にフォント情報を格納した構造体を渡します。

 
カスタムフォントの取得

自由にフォントを使いたい場合は、論理フォントを作成します。論理フォントの作成にはCreateFontIndirect関数を使います。


HFONT CreateFontIndirect(
  CONST LOGFONT
*lplf   // フォントの特性
);

LOGFONT 構造体

typedef struct tagLOGFONT {



 LONG lfHeight;                 
// フォントの高さ



 LONG lfWidth;                  
// 平均文字幅



 LONG lfEscapement;             
// 文字送り方向の角度



 LONG lfOrientation;            
// ベースラインの角度



 LONG lfWeight;                 
// フォントの太さ



 BYTE lfItalic;                 
// 斜体



 BYTE lfUnderline;              
// 下線



 BYTE lfStrikeOut;              
// 取り消し線



 BYTE lfCharSet;                
// 文字セットの識別子



 BYTE lfOutPrecision;           
// 出力精度



 BYTE lfClipPrecision;          
// クリッピング精度



 BYTE lfQuality;                
// 出力品質



 BYTE lfPitchAndFamily;         
// ピッチとファミリ



 TCHAR lfFaceName[LF_FACESIZE];
// フォント名



} LOGFONT;

lfHeight にはフォントの高さをしてします。0を指定するとデフォルト値になります。
lfWidth には文字幅を指定します。これも0を指定すればデフォルト値になりますので通常は0でよいでしょう。
lfEscapement は文字送り方向の角度を1/10度単位で指定します。
lfOrientation はベースラインの角度です。通常、lfEscapement と同じ値を指定します。
lfWeight はフォントの太さです。0を指定するとデフォルト値(普通の太さ)になります。
lfItalic 、lfUnderline 、lfStrikeOut はそれぞれ、斜体、下線、取り消し線で、TRUEを指定すると適用されます。
lfCharSet は文字セット指定します。通常はSHIFTJIS_CHARSETで良いでしょう。他にANSI_CHASESTが指定できます。
lfOutPrecision は出力の精度を指定します。通常OUT_DEFAULT_PRECISで良いでしょう。
lfClipPrecision はクリッピング精度を指定します。通常CLIP_DEFAULT_PRECISで良いでしょう。
lfQuality は出力品質です。ANTIALIASED_QUALITYを指定するとアンチエイリアス処理がかかります。そのほかに、
DEFAULT_QUALITY:デフォルト
CLEARTYPE_QUALITY:クリアタイプ表示
NONANTIALIASED_QUALITY:アンチエイリアスなし
などを指定することができます。
lfPitchAndFamily は、フォントのピッチとファミリを指定します。フォント名で指定したフォントが存在しなかったときに使われるフォントになります。
ピッチにはDEFAULT_PITCH(規定値)、FIXED_PITCH(固定幅)、VARIABLE_PITCH (可変幅)のいずれかを指定します。
ファミリには
FF_DECORATIVE:装飾つきフォント
FF_DONTCARE:デフォルトフォント
FF_ROMAN:プロポーショナルフォント
FF_SCRIPT:手書き風フォント
FF_SWISS:プロポーショナルフォント
の中からいづれかを指定します。
lfFaceName にはフォント名を指定します。

フォントが不要になったら、DeleteObject関数で削除します。

SelectObject関数

フォントを使用するにはSelectObjectでフォントを選択して有効にする必要があります。 

SelectObject関数
GDIオブジェクトを選択します。

HGDIOBJ SelectObject(
 HDC hdc,          
// デバイスコンテキストのハンドル
 HGDIOBJ hgdiobj   
// オブジェクトのハンドル
);


この関数は同じタイプの以前のオブジェクトを置き換えます。

戻り値に置き換えが発生する前のオブジェクトのハンドルが返ります。このハンドルを使用し、フォントを使用し終わった時にフォントを必ず元の(既定)オブジェクトに置き換えるようにしましょう。
以下のソースは、置き換えが発生する前のオブジェクトのハンドルをhFontOldに格納し、フォントの描画が終わったら、フォントを元に戻しています。

hFontOld = SelectObject(hdc,hFont);   // フォントを設定する
// ここで文字の描画を行う
SelectObject(hdc,hFontOld);    // フォントを元に戻す

ではソースを見てみましょう。 

// text003.cpp
//
// Windowに文字を表示する

#include <windows.h
>
#include <tchar.h
>
#include <strsafe.h
>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM
);
ATOM InitApp(HINSTANCE
);
HWND InitInstance(HINSTANCE, int
);

WCHAR szClassName[] = _T("win02");
// ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd
)
{
   MSG msg
;
   BOOL bRet
;
   HWND hWnd
;

   if (!InitApp(hInstance
))
       return FALSE
;
   if (!(hWnd = InitInstance(hInstance,nShowCmd
)))
       return FALSE
;
   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
       if (bRet == -1
){
           break
;
       } else
{
           TranslateMessage(&msg
);
           DispatchMessage(&msg
);
       
}
   
}
   return (int)msg.wParam
;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst
)
{
   WNDCLASS wc
;
   wc.style        = CS_HREDRAW|CS_VREDRAW
;
   wc.lpfnWndProc  = WndProc;  
// プロシージャ名
   wc.cbClsExtra   = 0
;
   wc.cbWndExtra   = 0
;
   wc.hInstance    = hInst
;
   wc.hIcon        = NULL;     
// 未サポート
   wc.hCursor      = NULL;     
// 未サポート
   wc.hbrBackground= (HBRUSH) COLOR_WINDOW
;
   wc.lpszMenuName = NULL;     
// 未サポート
   wc.lpszClassName=(LPCTSTR) szClassName
;

   return (RegisterClass(&wc
));
}

// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd
)
{
   HWND hWnd
;

   hWnd = CreateWindow(szClassName,_T("Window Title"),
       WS_CLIPCHILDREN,    
// ウィンドウの種類
       CW_USEDEFAULT,      
// x座標
       CW_USEDEFAULT,      
// y座標
       CW_USEDEFAULT,      
// 幅
       CW_USEDEFAULT,      
// 高さ
       NULL,               
// 親ウィンドウのハンドル。親を作るのでNULL
       NULL,               
// メニューハンドルまたは子ウィンドウID
       hInst,              
// インスタンスハンドル
       NULL
);
   if (!hWnd
)
       return FALSE
;
   ShowWindow(hWnd, nShowCmd
);
   UpdateWindow(hWnd
);
   return hWnd
;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp
)
{
   PAINTSTRUCT ps
;
   HDC hdc
;
   LPTSTR lpszStr= _T("WindowsMobile Win32APIプログラミング"
);
   size_t size;        
// 文字列のサイズを格納する
   StringCchLength(lpszStr,STRSAFE_MAX_CCH,&size);
// 安全な文字列取得

   static HFONT hFont
;
   HGDIOBJ hFontOld
;

   switch (msg
){
       
// ウィンドウプロシージャは、ウィンドウが作成された直後で
       
// ウィンドウが表示される前にWM_CREATEメッセージを受け取ります。
       case WM_CREATE
:
           LOGFONT logicalFont;    
// フォントの属性を定義

           logicalFont.lfHeight        = 20;               
// フォントの高さ
           logicalFont.lfWidth         = 0;                
// 平均文字幅
           logicalFont.lfEscapement    = 0;                
// 文字送り方向の角度
           logicalFont.lfOrientation   = 0;                
// ベースラインの角度
           logicalFont.lfWeight        = FW_BOLD;          
// フォントの太さ
           logicalFont.lfItalic        = TRUE;             
// 斜体
           logicalFont.lfUnderline     = TRUE;             
// 下線
           logicalFont.lfStrikeOut     = TRUE;             
// 取り消し線
           logicalFont.lfCharSet       = SHIFTJIS_CHARSET; 
// 文字セットの識別子
           logicalFont.lfOutPrecision  = OUT_DEFAULT_PRECIS; 
// 出力精度
           logicalFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
// クリッピング精度
           logicalFont.lfQuality       = ANTIALIASED_QUALITY;
// 出力品質
           logicalFont.lfPitchAndFamily= FIXED_PITCH | FF_MODERN;  
// ピッチとファミリ
           
// フォント名
           StringCchCopy(logicalFont.lfFaceName,32,_T("MS ゴシック"
));

           hFont = CreateFontIndirect(&logicalFont
);

       case WM_PAINT
:
           hdc = BeginPaint(hWnd,&ps);     
// 描画処理を開始します。
           hFontOld = SelectObject(hdc,hFont
);
           ExtTextOut
(
               hdc,    
// デバイスコンテキストのハンドル
               0,      
// 開始位置(基準点)の x 座標
               20,     
// 開始位置(基準点)の y 座標
               NULL,   
// 長方形領域の使い方のオプション
               NULL,   
// 長方形領域の入った構造体へのポインタ
               lpszStr,
// 文字列
               size,   
// 文字数
               NULL    
// 文字間隔の入った配列
               
);
           SelectObject(hdc,hFontOld
);
           EndPaint(hWnd,&ps
);
           break
;
       case WM_DESTROY
:
           DeleteObject(hFont
);    // フォントの破棄を忘れずに行うこと!
           PostQuitMessage(0
);
           break
;
       default
:
           return (DefWindowProc(hWnd, msg, wp, lp
));
   
}
   return 0
;
}

WM_CREATEメッセージ
ウィンドウプロシージャは、ウィンドウが作成された直後のウィンドウが表示される前にWM_CREATEメッセージを受け取ります。

このプログラムでは、ウインドウプロシージャがWM_CREATEメッセージを受け取った時点で、CreateFontIndirect関数でカスタムフォント(論理フォント)を作成しています。

WM_DESTROYメッセージ(プログラムの終了時)を受け取った時に、DeleteObject関数を呼び出して作成した論理フォントを削除しています。

 

今日はここまで。

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/25(水) 23:24:42|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

006:文字を表示する

TextOutは使えません 
TextOutは,最もシンプルな文字列描画APIです。まず文字を表示するサンプルとしてTextOutが紹介されることが多いのですが、Windows MobileにはTextOutがありません。
その代わりExtTextOutを使用します。ExtTextOutはTextOutの拡張版になります。

ExtTextOut
現在選択されているフォント、背景色、および文字の色を使ってテキストを描画します。必要に応じて、クリッピングしたり不透明にするための長方形領域を指定することもできます。

BOOL ExtTextOut(
 HDC hdc,          
// デバイスコンテキストのハンドル
 int X,            
// 開始位置(基準点)の x 座標
 int Y,            
// 開始位置(基準点)の y 座標
 UINT fuOptions,   
// 長方形領域の使い方のオプション
 CONST RECT *lprc,
// 長方形領域の入った構造体へのポインタ
 LPCTSTR lpString,
// 文字列
 UINT cbCount,     
// 文字数
 CONST INT *lpDx   
// 文字間隔の入った配列
);


hdcにはデバイスコンテキストのハンドルを指定します。
x,yにはそれぞれ論理x座標、論理y座標を指定します。文字列を囲む長方形の左上を基準とします。
この座標系はWindowの左上を原点0とし、右方向へ+x,下方向へ+yとなっています。(数学でよく使ったxy座標系からは、y軸の+-が反転しています)
fuOptionsは長方形領域の使い方をオプションで指定します。このパラメータは省略可能です。
lpString に文字列を指定します。
cbCount には文字列に格納されている文字の数を指定します。
lpDx は文字間隔の入った配列です。NULL を指定すると、既定の文字間隔を使います。

デバイスコンテキスト
ExtTextOut関数のhdcに指定するデバイスコンテキストとは何でしょうか。これは描画デバイスの情報を管理している値です。描画デバイスにはプリンタ、プロッタ、ディスプレイ・・・と様々なデバイスがあります。プリンタに出力する場合はプリンタのデバイスコンテキストを取得し描画を行い、ディスプレイに出力する場合はディスプレイのデバイスコンテキストを取得して描画を行います。描画の方法はGDI(Graphics Device Interface)によって抽象化されているので、プリンタに描画するときもディスプレイに描画するときも同じ関数を使用することができます。便利ですね。しかしWindowsMobileの場合は描画デバイスといえばほとんどがディスプレイになるでしょうね。

デバイスコンテキストの取得
ディスプレイのデバイスコンテキストを取得するには、GetDC関数を使います。

GetDC関数
指定されたウィンドウのクライアント領域を取得します。

HDC GetDC(
 HWND hWnd   
// ウィンドウのハンドル
);


hWnd デバイスコンテキストの取得対象となるウィンドウのハンドルを指定します。NULL を指定すると、GetDC は画面全体を表すデバイスコンテキストを取得します。

デバイスコンテキストはHDC型の戻り値として返されます。画面に何か描画を行う関数はこの値を必要とするので、GetDCの戻り値を渡します。

デバイスコンテキストの開放
取得したデバイスコンテキストは、いらなくなったら開放してあげなくてはなりません。

ReleaseDC関数
デバイスコンテキストを解放し、他のアプリケーションから使えるようにします。

int ReleaseDC(
 HWND hWnd,  
// ウィンドウのハンドル
 HDC hDC     
// デバイスコンテキストのハンドル
);


描画の準備
BeginPaint関数は、指定されたウィンドウに対して描画の準備をします。
HDC BeginPaint(
   HWND  hwnd,             
//  ウィンドウのハンドル
   LPPAINTSTRUCT  lpPaint  
//  描画情報を持つ構造体へのポインタ
);


hwnd
再描画するウィンドウのハンドルを識別します。
lpPaint 描画情報を受け取る PAINTSTRUCT 構造体へのポインタです。
PAINTSTRUCT 構造体 ウィンドウのクライアント領域を描画するときに使うことのできる情報を保持します。

typedef struct tagPAINTSTRUCT {
  HDC hdc;             
// 描画に使われるデバイス コンテキストを識別します。
  BOOL fErase;         
// 背景を再描画する必要があるかどうかを指定します。
  RECT rcPaint;        
// 描画が要求されている四角形の左上隅と右下隅を指定します。
  BOOL fRestore;       
// Windows が内部的に使います。
  BOOL fIncUpdate;     
// Windows が内部的に使います。
  BYTE rgbReserved[16];
// Windows が内部的に使う予約されているメモリ ブロックです。
} PAINTSTRUCT;


描画の終了
EndPaint関数は指定されたウィンドウ内の描画の終わりを示します。
BeginPaint 関数を呼び出したら必ず描画の最後でEndPaint 関数を呼び出さなければなりません

EndPaint関数
指定されたウィンドウ内の描画の終わりを示します。

BOOL EndPaint(
 HWND hWnd,                  
// ウィンドウのハンドル
 CONST PAINTSTRUCT *lpPaint  
// 描画データ
);


では、画面に
「Windows Mobileで最初の文字列を表示する」と「WindowsMobile Win32APIプログラミング」という文字を表示するプログラムを作ってみます。

// text002.cpp
//
// Windowに文字を表示する

#include <windows.h
>
#include <tchar.h
>
#include <strsafe.h
>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM
);
ATOM InitApp(HINSTANCE
);
HWND InitInstance(HINSTANCE, int
);

WCHAR szClassName[] = _T("win02");
// ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd
)
{
   MSG msg
;
   BOOL bRet
;
   HWND hWnd
;
   HDC hdc;    
// デバイスコンテキストのハンドル
   LPTSTR lpszStr= _T("Windows Mobileで最初の文字列を表示する"
);
   size_t size;        
// 文字列のサイズを格納する

   StringCchLength(lpszStr,STRSAFE_MAX_CCH,&size);
// 安全な文字列取得

   if (!InitApp(hInstance
))
       return FALSE
;
   if (!(hWnd = InitInstance(hInstance,nShowCmd
)))
       return FALSE
;

   
// 「最初の文字列」を描画
   hdc = GetDC(hWnd
);
   ExtTextOut
(
       hdc,    
// デバイスコンテキストのハンドル
       0,      
// 開始位置(基準点)の x 座標
       0,      
// 開始位置(基準点)の y 座標
       NULL,   
// 長方形領域の使い方のオプション
       NULL,   
// 長方形領域の入った構造体へのポインタ
       lpszStr,
// 文字列
       size,   
// 文字数
       NULL    
// 文字間隔の入った配列
       
);


   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
       if (bRet == -1
){
           break
;
       } else
{
           TranslateMessage(&msg
);
           DispatchMessage(&msg
);
       
}
   
}
   return (int)msg.wParam
;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst
)
{
   WNDCLASS wc
;
   wc.style        = CS_HREDRAW|CS_VREDRAW
;
   wc.lpfnWndProc  = WndProc;  
// プロシージャ名
   wc.cbClsExtra   = 0
;
   wc.cbWndExtra   = 0
;
   wc.hInstance    = hInst
;
   wc.hIcon        = NULL;     
// 未サポート
   wc.hCursor      = NULL;     
// 未サポート
   wc.hbrBackground= (HBRUSH) COLOR_WINDOW
;
   wc.lpszMenuName = NULL;     
// 未サポート
   wc.lpszClassName=(LPCTSTR) szClassName
;

   return (RegisterClass(&wc
));
}

// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd
)
{
   HWND hWnd
;

   hWnd = CreateWindow(szClassName,_T("Window Title"),
       WS_CLIPCHILDREN,    
// ウィンドウの種類
       CW_USEDEFAULT,      
// x座標
       CW_USEDEFAULT,      
// y座標
       CW_USEDEFAULT,      
// 幅
       CW_USEDEFAULT,      
// 高さ
       NULL,               
// 親ウィンドウのハンドル。親を作るのでNULL
       NULL,               
// メニューハンドルまたは子ウィンドウID
       hInst,              
// インスタンスハンドル
       NULL
);
   if (!hWnd
)
       return FALSE
;
   ShowWindow(hWnd, nShowCmd
);
   UpdateWindow(hWnd
);
   return hWnd
;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp
)
{
   PAINTSTRUCT ps
;
   HDC hdc
;
   LPTSTR lpszStr= _T("WindowsMobile Win32APIプログラミング"
);
   size_t size;        
// 文字列のサイズを格納する
   StringCchLength(lpszStr,STRSAFE_MAX_CCH,&size);
// 安全な文字列取得

   switch (msg
){
       case WM_PAINT
:
           hdc = BeginPaint(hWnd,&ps);     
// 描画処理を開始します。 
           ExtTextOut(
               hdc,    
// デバイスコンテキストのハンドル
               0,      
// 開始位置(基準点)の x 座標
               20,     
// 開始位置(基準点)の y 座標
               NULL,   
// 長方形領域の使い方のオプション
               NULL,   
// 長方形領域の入った構造体へのポインタ
               lpszStr,
// 文字列
               size,   
// 文字数
               NULL    
// 文字間隔の入った配列
               
);
           EndPaint(hWnd,&ps
);
           break
;
       case WM_DESTROY
:
           PostQuitMessage(0
);
           break
;
       default
:
           return (DefWindowProc(hWnd, msg, wp, lp
));
   
}
   return 0
;
}



実行すると、ウィンドウに文字が表示されます。

最初の文字「Windows Mobileで最初の文字列を表示する」は、WinMain関数内で描画し、「WindowsMobile Win32APIプログラミング」の文字はウインドウプロシージャWndProc内で描画しています。その違いを見てみましょう。


「Windows Mobileで最初の文字列を表示する」は、他の画面に一度隠されると、その部分が消えてしまいます。これは、WinMain関数内でウィンドウ生成後に1度しか描画していないためです。では「WindowsMobile Win32APIプログラミング」の文字はなぜ消えないのでしょうか。

Windowsではウィンドウの一部、または全部に書き直しの必要が生じた場合には、WM_PAINTというメッセージを発行します。ウィンドウプロシージャ内でこのメッセージを受け取った場合は、再度描画処理を行う必要があります。「WindowsMobile Win32APIプログラミング」の文字は、WndProc内のswitch文でWM_PAINTメッセージがきたら文字を描画するようになっているため、文字列が他の画面に隠されても再度描画を行っているので文字が消えないのです

今日はここまで。

 

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/24(火) 23:56:24|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

005:MessageBoxを使ってhello,world

さて、ようやくウィンドウが表示できるようになりました。そろそろ何か表示をさせてみましょうか。まずは比較的簡単にメッセージを表示させることの出来るMessageBoxを使ってhello,worldを行います。

MessageBox関数

int MessageBox(
    HWND hWnd,          // オーナーウィンドウのハンドル
    LPCTSTR lpText,    
// メッセージボックス内のテキスト
    LPCTSTR lpCaption, 
// メッセージボックスのタイトル
    UINT uType         
// メッセージボックスのスタイル
);

hWndにはオーナーウィンドウのハンドルを指定します。NULLを指定すればオーナウィンドウなしのメッセージボックスになります。
lpTextには、メッセージボックスに表示したい文字列を指定します。_T()マクロを使用しています。
lpCaptionには、メッセージボックスのタイトルを指定します。
uTypeには、メッセージボックスの内容と動作を指定します。以下のいくつかのフラグを組み合わせて使用することができます。

ボタン

MB_OK 

メッセージボックスに[OK]プッシュボタンだけを表示します。これは既定のメッセージボックスタイプです。
MB_OKCANCEL メッセージボックスに[OK]、[キャンセル]の各プッシュボタンを表示します。
MB_RETRYCANCEL メッセージボックスに[再試行]、[キャンセル]の各プッシュボタンを表示します。
MB_YESNOメッセージボックスに[はい]、[いいえ]の各プッシュボタンを表示します。
MB_YESNOCANCEL メッセージボックスに[はい]、[いいえ]、[キャンセル]の各プッシュボタンを表示します。

アイコン

MB_ICONEXCLAMATION感嘆符(!)アイコンを表示します。
MB_ICONINFORMATION丸の中に小文字の「i」が描かれたアイコンを表示します。

MB_ICONQUESTION

疑問符(?)アイコンを表示します。
MB_ICONSTOP停止マークアイコンを表示します。

デフォルトボタン

MB_DEFBUTTON11番目のボタンを既定のプッシュボタンにします。
MB_DEFBUTTON22番目のボタンを既定のプッシュボタンにします。
MB_DEFBUTTON3 3番目のボタンを既定のプッシュボタンにします。
MB_DEFBUTTON4 4番目のボタンを既定のプッシュボタンにします。

その他のオプション

MB_TOPMOSTメッセージボックスを最前面ウィンドウとして作成します。

uTypeにはそのほかにも色々なオプションがあります。詳しくはMSDNの「プラットフォーム SDK」で確認してみてください。

ちなみにMessageBoxはUNICODEマクロが定義されているので実際にはMessageBoxWが呼ばれます。

int MessageBoxW(
    HWND hWnd ,         // オーナーウィンドウのハンドル
    LPCWSTR lpText,     // メッセージボックス内のテキスト
    LPCWSTR lpCaption,  // メッセージボックスのタイトル
    UINT uType);        // メッセージボックスのスタイル
);

サンプルは次のような感じになります。

    // MessageBoxサンプル
    MessageBox(hWnd,_T("こんにちは,世界"),_T("TITLE"),MB_OK);
   


次に「はい」、「いいえ」を使ったダイアログボックスを作ってみます。
MessageBoxの第4引数にMB_YESNOや、MB_YESNOCANCELを指定することで「はい」「いいえ」や、「はい」「いいえ」「キャンセル」を選択することができます。MessageBoxの戻り値でどのボタンが押されたかを判定することができます。

    // YES,NO,キャンセルを持つメッセージボックス
    int iRtnValue;
    iRtnValue = MessageBox(hWnd,_T("あなたは男性ですか?"),_T("性別"),MB_YESNOCANCEL);

   switch (iRtnValue)
   
{
   case IDYES
:
       MessageBox(hWnd,_T("「はい」が選択されました"),_T("男性"),MB_OK
);
       break
;
   case IDNO
:
       MessageBox(hWnd,_T("「いいえ」が選択されました"),_T("女性"),MB_OK
);
       break
;
   case IDCANCEL
:
       MessageBox(hWnd,_T("「×」が選択されました"),_T("分からない"),MB_OK
);
       break
;
   }

全ソースを表示します。

WinMain関数内で描画したウィンドウのハンドルを取得するために、InitInstance()関数の戻り値を BOOLからHWNDに変更してあります。 そのほかは、MessageBox関数を追加した以外変更していません。

// text001.cpp
//
// "hello, world"サンプル

#include <windows.h>
#include <tchar.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
HWND InitInstance(HINSTANCE, int);

WCHAR szClassName[] = _T("win02"); // ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
   MSG msg;
   BOOL bRet;
   HWND hWnd;




   if (!InitApp(hInstance))
       return FALSE;
   if (!(hWnd = InitInstance(hInstance,nShowCmd)))
       return FALSE;

   // MessageBoxサンプル
   MessageBox(hWnd,_T("こんにちは,世界"),_T("TITLE"),MB_OK);

   // YES,NO,キャンセルを持つメッセージボックス
   int iRtnValue;
   iRtnValue = MessageBox(hWnd,_T("あなたは男性ですか?"),_T("性別"),MB_YESNOCANCEL);

   switch (iRtnValue)
   {
   case IDYES:
       MessageBox(hWnd,_T("「はい」が選択されました"),_T("男性"),MB_OK);
       break;
   case IDNO:
       MessageBox(hWnd,_T("「いいえ」が選択されました"),_T("女性"),MB_OK);
       break;
   case IDCANCEL:
       MessageBox(hWnd,_T("「×」が選択されました"),_T("分からない"),MB_OK);
       break;
   }

   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
       if (bRet == -1){
           break;
       } else {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
       }
   }
   return (int)msg.wParam;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst)
{
   WNDCLASS wc;
   wc.style        = CS_HREDRAW|CS_VREDRAW;
   wc.lpfnWndProc  = WndProc;  // プロシージャ名
   wc.cbClsExtra   = 0;
   wc.cbWndExtra   = 0;
   wc.hInstance    = hInst;
   wc.hIcon        = NULL;     // 未サポート
   wc.hCursor      = NULL;     // 未サポート
   wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
   wc.lpszMenuName = NULL;     // 未サポート
   wc.lpszClassName=(LPCTSTR) szClassName;

   return (RegisterClass(&wc));
}

// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd)
{
   HWND hWnd;

   hWnd = CreateWindow(szClassName,_T("Window Title"),
       WS_CLIPCHILDREN,    // ウィンドウの種類
       CW_USEDEFAULT,      // x座標
       CW_USEDEFAULT,      // y座標
       CW_USEDEFAULT,      // 幅
       CW_USEDEFAULT,      // 高さ
       NULL,               // 親ウィンドウのハンドル。親を作るのでNULL
       NULL,               // メニューハンドルまたは子ウィンドウID
       hInst,              // インスタンスハンドル
       NULL);
   if (!hWnd)
       return FALSE;
   ShowWindow(hWnd, nShowCmd);
   UpdateWindow(hWnd);
   return hWnd;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
   switch (msg){
       case WM_DESTROY:
           PostQuitMessage(0);
           break;
       default:
           return (DefWindowProc(hWnd, msg, wp, lp));
   }
   return 0;
}

きょうはここまで。

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/23(月) 23:59:19|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

004:クロスプラットフォームに対応する

クロスプラットフォームに対応する

今日はWindows Mobile特有の文字の取り扱いについて説明します。

Windows MobileはUnicodeプラットフォームです。文字はUnicodeとして取り扱うのが基本となります。そのためにはUnicodeに対応した文字列関数を使用する必要があります。使用するデータ型はchar型ではなく、wchar_tとなります。

結論から言うと文字列型にはTCHAR LPTSTR を使用すれば問題ありません。
これらの関数は、環境によって切り替える(UNICODE環境ではUnicode対応のデータ型を使用してくれる)汎用テキスト型です。環境に依存するCHAR と LPSTR は使用しません。

文字列定数の場合、Unicodeであれば、
WCHAR szStr[] = L"こんにちは世界";
と、L接頭辞を指定します。

しかし実際の文字列定数と文字定数には _T() マクロを使用します。たとえば、_T("string") や _T('s') を使用し、L"string" や L's' は使用しません。
_T() マクロは、UnicodeであればL接頭辞をつけてくれ、そうでなければそのままの文字として解釈します。そのためL接頭辞を使用するより_T() マクロを使用したほうが他のWindows環境への移植性が上がるわけです。

Windows Mobile環境のみで使用するコードであることが明白であれば、これらを考慮する必要はありませんが移植可能なコーディングの慣例に従うように心がけておくことは無駄ではないでしょう。

では先ほどのwin01を修正してみましょう。
_T() マクロを使用するために、

#include <tchar.h>

を追加します。

WNDCLASSWは、WNDCLASSに変更
RegisterClassWは、RegisterClassに変更
CreateWindowWはCreateWindowに変更します。UNICODEマクロが定義されているのでそれぞれW付きの関数に展開されます。

変更点を赤文字で示します。

// win02.cpp

#include <windows.h>
#include <tchar.h>     //追加

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);

WCHAR szClassName[] = _T("win02"); // ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
 MSG msg;
 BOOL bRet;

 if (!InitApp(hInstance))
  return FALSE;
 if (!InitInstance(hInstance,nShowCmd))
  return FALSE;
 while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
  if (bRet == -1){
   break;
  } else {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 return (int)msg.wParam;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst)
{
 WNDCLASS wc;
 wc.style  = CS_HREDRAW|CS_VREDRAW;
 wc.lpfnWndProc = WndProc; // プロシージャ名
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hInstance = hInst;
 wc.hIcon  = NULL;  // 未サポート
 wc.hCursor  = NULL;  // 未サポート
 wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
 wc.lpszMenuName = NULL;  // 未サポート
 wc.lpszClassName=(LPCTSTR) szClassName;

 return (RegisterClass(&wc));
}

// ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nShowCmd)
{
 HWND hWnd;

 hWnd = CreateWindow(szClassName,_T("Window Title"),
  WS_CLIPCHILDREN, // ウィンドウの種類
  CW_USEDEFAULT,  // x座標
  CW_USEDEFAULT,  // y座標
  CW_USEDEFAULT,  // 幅
  CW_USEDEFAULT,  // 高さ
  NULL,    // 親ウィンドウのハンドル。親を作るのでNULL
  NULL,    // メニューハンドルまたは子ウィンドウID
  hInst,    // インスタンスハンドル
  NULL);
 if (!hWnd)
  return FALSE;
 ShowWindow(hWnd, nShowCmd);
 UpdateWindow(hWnd);
 return TRUE;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
 switch (msg){
  case WM_DESTROY:
   PostQuitMessage(0);
   break;
  default:
   return (DefWindowProc(hWnd, msg, wp, lp));
 }
 return 0;
}

今日はここまで。

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/22(日) 07:50:37|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

003:ウィンドウを作る

ウィンドウを作る

まずはWin32APIの基礎中の基礎、ウィンドウを作ってみます。
何もしないウィンドウを作ってみましょう。

[ファイル(F)]→[新規作成(N)]→[プロジェクト(P)]を選び、[新しいプロジェクト]ウィンドウを開きます。



プロジェクトの種類:スマートデバイス
テンプレート:Win32 スマートデバイス プロジェクト
プロジェクト名:win01

上記設定を行い[OK]ボタンを押します。

Win32 スマートデバイス プロジェクト ウィザード画面になります。

[次へ>]ボタンを押します。

プラットフォームの選択画面で、Windows Mobile 5.0 PocketPC SDKと、Windows Mobile 6 Professional SDKを選択します。
[次へ>]ボタンを押します。

プロジェクトの設定画面になります。
今回は、Windowsアプリケーションを選択しWindowの雛形を生成しましたが、今回は自分で一から作成してみたいと思います。追加のオプションで「空のプロジェクト」を選択します。



アプリケーションの種類:Windowsアプリケーション
追加のオプション:空のプロジェクト

上記設定を行い、[完了]ボタンを押します。
空っぽのプロジェクトが作成できました。

ここにソースを追加していきます。
ソリューションエクスプローラの「ソースファイル」を右クリックし、メニューから[追加(D)]→[新しい項目(W)]を選択します。

「新しい項目の追加」ウィンドウで

カテゴリ:コード
テンプレート:C++ファイル(cpp)
ファイル名:win01

上記を選択・入力し[追加]ボタンを押します。

追加されたファイルに、以下の内容を入力します。
// win01.cpp

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);

WCHAR szClassName[] = L"win01"; // ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine,int nShowCmd)
{
 MSG msg;
 BOOL bRet;

 if (!InitApp(hInstance))
  return FALSE;
 if (!InitInstance(hInstance,nShowCmd))
  return FALSE;
 while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
  if (bRet == -1){
   break;
  } else {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 return (int)msg.wParam;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst)
{
 WNDCLASSW wc;
 wc.style  = CS_HREDRAW|CS_VREDRAW;
 wc.lpfnWndProc = WndProc; // プロシージャ名
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hInstance = hInst;
 wc.hIcon  = NULL;  // 未サポート
 wc.hCursor  = NULL;  // 未サポート
 wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
 wc.lpszMenuName = NULL;  // 未サポート
 wc.lpszClassName=(LPCWSTR) szClassName;

 return (RegisterClassW(&wc));
}

// ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nShowCmd)
{
 HWND hWnd;

 hWnd = CreateWindowW(szClassName,L"Window Title",
  WS_CLIPCHILDREN, // ウィンドウの種類
  CW_USEDEFAULT,  // x座標
  CW_USEDEFAULT,  // y座標
  CW_USEDEFAULT,  // 幅
  CW_USEDEFAULT,  // 高さ
  NULL,    // 親ウィンドウのハンドル。親を作るのでNULL
  NULL,    // メニューハンドルまたは子ウィンドウID
  hInst,    // インスタンスハンドル
  NULL);
 if (!hWnd)
  return FALSE;
 ShowWindow(hWnd, nShowCmd);
 UpdateWindow(hWnd);
 return TRUE;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
 switch (msg){
  case WM_DESTROY:
   PostQuitMessage(0);
   break;
  default:
   return (DefWindowProc(hWnd, msg, wp, lp));
 }
 return 0;
}


それではF5キーを押してビルド&実行してみましょう。

ただの真っ白なウィンドウが作成されました。
画像を見てわかるとおり、下部のメニュー部分が白くなっています。
これはタスクバーの高さを考慮していないためです。
今後解決していきます。

プログラムの構造

ではプログラムを見ていきます。
プログラムは次のような構造をしています。

int WINAPI WinMain()
{
 1.ウィンドウクラスの登録
 2.ウィンドウの生成
 while(メッセージがあるか)
 {
  3.メッセージがあればウインドウプロシージャへ送出
 }
}

LRESULT CALLBACK WndProc()
{
 4.ウインドウに発生した色々な処理
 (マウスのクリックや、ウインドウサイズの変更など)
 に対する処理を記述する
}


WinMain関数がアプリケーションエントリーポイントになります。エントリーポイントとはプログラムの開始点のことです。WindowsアプリケーションはWinMain関数から始まると覚えてください。

WinMain関数の中ではウィンドウクラスの登録とウィンドウの生成を行います。
ウィンドウが生成されたら、メッセージループとなります。
Windowsでは、ウインドウに発生した色々な処理(マウスのクリックや、ウインドウサイズの変更など)がメッセージとしてやってきます。これらを適切に処理してやる必要があります。
これらの処理を記述するのがウィドウプロシージャです。プログラマがやりたいことをウィンドウプロシージャに記述します。

WinMain→ウィンドを作成→その後、メッセージをひたすら待ち続ける。

ウィンドウに発生する色々なイベント(メッセージ)→ウインドウプロシージャへ伝えられる。

ウィンドウクラス

ウィンドウを作るにはまず、ウィンドウクラスを登録する必要があります。
ウィンドウクラスを登録するにはWNDCLASSW構造体のメンバに各種設定を行います。
その後、RegisterClassW APIでウィンドウクラスを登録します。これはInitApp関数で行っています。

typedef struct {
    UINT style;   // ウインドウスタイル
    WNDPROC lpfnWndProc; // ウィンドウプロシージャ
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance; // インスタンスハンドル
    HICON hIcon;  // アイコン
    HCURSOR hCursor;  // カーソル
    HBRUSH hbrBackground; // 背景ブラシ
    LPCTSTR lpszMenuName; // メニュー名
    LPCTSTR lpszClassName; // クラス名
} WNDCLASS, *PWNDCLASS;

style ではクラスのスタイルを指定します。
CS_VERDRAW,CS_HREDRAW,CS_DBLCLKS,CS_PARENTDC,CS_NOCLOSEがサポートされます。
CS_VERDRAW:クライアント領域の幅が変更された場合に再描画を行う
CS_HREDRAW:クライアント領域の高さが変更された場合に再描画を行う
CS_DBLCLKS:ダブルクリックを検出する
CS_PARENTDC:子ウィンドウが親ウィンドウで描画されるように子ウィンドウのクリッピング領域を親ウィンドウのクリッピング領域に設定する。CS_PARENTDCスタイルを指定したウィンドウは子ウィンドウが親ウィンドウ上で描画できるようになります。
CS_NOCLOSE:ウィンドウ・メニューの[閉じる]を無効にします。

hIcon、hCursor、hbrBackgroundはWindows MobileではサポートされていませんのでNULLをセットします。

RegisterClassW APIを使用してウィンドウクラスを登録します。引数にはWNDCLASS構造体へのポインタを指定します。

ウィンドウ作成

ウインドウ作成にはCreateWindowW() APIを使用します。

HWND CreateWindow(
  LPCTSTR lpClassName,  // 登録されているクラス名
  LPCTSTR lpWindowName, // ウィンドウ名
  DWORD dwStyle,        // ウィンドウスタイル
  int x,                // ウィンドウの横方向の位置
  int y,                // ウィンドウの縦方向の位置
  int nWidth,           // ウィンドウの幅
  int nHeight,          // ウィンドウの高さ
  HWND hWndParent,      // 親ウィンドウまたはオーナーウィンドウのハンドル
  HMENU hMenu,          // メニューハンドルまたは子ウィンドウ ID
  HINSTANCE hInstance,  // アプリケーションインスタンスのハンドル
  LPVOID lpParam        // ウィンドウ作成データ
);

x、y、nWidth、nHeightにCW_USEDEFAULTを指定すると、全画面ウィンドウになります。

dwStyleには次のようなスタイルがあります。
WS_CLIPCHILDREN:親の描画で子ウインドウの部分をクリッピングします。親ウィンドウを作成する場合、このスタイルを使用します。
WS_BORDER:細い境界線のウィンドウを作成します。
WS_CAPTION:タイトルバーを持つウィンドウを作成します。
WS_CHILD:子ウィンドウ
WS_CLIPSIBLINGS:
特定の子ウィンドウがWM_PAINTメッセージを受け取る場合、WS_CLIPSIBLINGSスタイルは更新される子ウィンドウの領域からの他のすべてのオーバーラップする子供ウィンドウをクリップ(切り取り)ます。
WS_CLIPSIBLINGS が指定されていない場合に子ウィンドウがオーバーラップしていると子ウィンドウのクライアント領域内を描画するときに重なっている子ウィンドウのクライアント領域内にも描画されます

hWndParentには親ウィンドウのハンドルを指定しますが、親ウィンドウを作成する場合はNULLを指定します。
hInstanceにはインスタンスハンドルを指定します。
lpParamにはウィンドウ作成データを指定します。必要ない場合はNULLを指定します。


メッセージループ

Windowの生成が完了した後は、whileループになっています。
ウインドウに発生した色々な処理(マウスのクリックや、ウインドウサイズの変更など)は一旦メッセージキューという所にたまっています。それを取り出して、そのメッセージに合わせた処理を行う必要があります。メッセージを取り出すには、GetMessageを使用します。

BOOL GetMessage(
  LPMSG lpMsg,         // メッセージ情報
  HWND hWnd,           // ウィンドウのハンドル
  UINT wMsgFilterMin,  // 最初のメッセージ
  UINT wMsgFilterMax   // 最後のメッセージ
);

メッセージキューからメッセージを取得し、指定された構造体にそのメッセージを格納します。
GetMessageの戻り値は、WM_QUIT メッセージを取得した場合、0 が返ります。WM_QUIT メッセージはウィンドウを閉じることを要求するものです。
また、エラーが発生した場合には -1 が返ります。
0を受け取った場合はwhile文のメッセージループを抜けます。また-1の場合もbreakでメッセージループを抜けています。

取り出したメッセージは
DispatchMessageを使用して、メッセージをウィンドウプロシージャに渡します。

DispatchMessage関数
ウィンドウプロシージャへメッセージをディスパッチ(送出)します。

LRESULT DispatchMessage(
  CONST MSG *lpmsg   // メッセージ情報
);

■ウィンドウプロシージャ

メッセージが、DispatchMessage関数によりウィンドウプロシージャへ送られます。
switch文によって、メッセージの種類を判定し、メッセージにあった処理を行います。
このプログラムでは、WM_DESTROYを受け取っています。WM_DESTROYはウィンドウが破棄されるときに送られてきます。そしてPostQuitMessageによりシステムにプログラム終了リクエストを送ります。

それ以外のメッセージは、DefWindowProc関数に渡して処理してもらっています。

DefWindowProc関数は既定のウィンドウプロシージャを呼び出し、アプリケーションが処理しない任意のウィンドウメッセージに対する既定の処理を行ってくれます。

WM_DESTROYを受け取るまでひたすらメッセージを待ち続けます。

今日はここまで。

テーマ:Windows Mobile - ジャンル:コンピュータ

  1. 2008/06/20(金) 06:53:37|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

002:Visual Studio 2005の起動

Visual Studio 2005の起動

[ファイル(F)]→[新規作成(N)]→[プロジェクト(P)]を選び、[新しいプロジェクト]ウィンドウを開きます。

 

プロジェクトの種類:スマートデバイス
テンプレート:Win32 スマートデバイス プロジェクト
プロジェクト名:test001

上記設定を行い[OK]ボタンを押します。

Win32 スマートデバイス プロジェクト ウィザード画面になります。

[次へ>]ボタンを押します。

プラットフォームの選択画面で、Windows Mobile 5.0 PocketPC SDKと、Windows Mobile 6 Professional SDKを選択します。

[次へ>]ボタンを押します。

プロジェクトの設定画面になります。


アプリケーションの種類:Windowsアプリケーション

上記設定を行い、[完了]ボタンを押します。
アプリケーションの雛形が作成されます。早速ビルド&実行してみましょう。
まず、プラットフォームを選択します。今回はWindows Mobile 6 Professional SDKを選択します。

次に、ターゲットデバイスを選択します。今回はJPN Windows Mobile 6 Professional VGA Emulatorを選択します。

JPN Windows Mobile XXXX Emulatorとあるものがエミュレータで、Windows Mobile XXXX Deviceとあるものが、実機での実行になります。

ちなみに、私の所有しているWM機であるAdvanded W-ZERO3[es]の解像度はWVGAなのですが、ターゲットデバイスの一覧にはWVGAのエミュレータが存在しません。これはあとで作成したいと思います。

[デバッグ(D)]→[デバッグ開始(S)]を選択するか、F5キーを押すと、エミュレータにプログラムが配置され、エミュレータが立ち上がり、プログラムが実行されます。

プログラムがビルドされていない場合は次の画面が表示されます。[はい(Y)]を選択してビルドを実行します。

エミュレータが立ち上がり、プログラムが実行されました。

今日はここまで。

  1. 2008/06/18(水) 21:33:12|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

001:Windows Mobile開発環境の構築

はじめに
Windows Mobile 開発の入門記事です。C++とWin32APIについて理解を深めていきます。
対象読者 C,C++の基礎的な知識を持っていてWindowsMobileで高速なアプリを開発したい方が本稿の対象読者です。 

ソフトバンクモバイルやドコモからもWindowsMobile搭載携帯電話が発売されるなど、WindowsMobileによる開発者は増えていくものと予測されます。
部品を張り付けて部品の設定や部品間の関係を指定することでアプリケーションソフトを開発する近年のRADツール開発しか経験の無い開発者にとってWin32APIによる開発は敷居の高いものです。
本稿ではC/C++とWin32APIを使用したネイティブアプリケーションによる高速なソフトウェの開発を説明します。
Win32APIの説明と同時に、WindowsMobile特有の機能についてもサンプルを交えながら検証していきます。

開発言語
Windows Mobileの開発にはC++を使った開発と.NET Compact Frameworkを使った開発があります。
C++での開発は「ネイティブ開発」と呼ばれ、Win32 AIPを駆使してプログラミングを行います。

一般的に開発の工数は増えますが、リソースの消費が少なく、高速に動作するプログラムが作成できます

.NET Compact Frameworkでの開発は、C#やVB.NETを使用して開発することができます。
こちらはRADな開発環境によりスピーディに開発を行うことができますが、作成したプログラムの起動が遅いなどのデメリットがあります。業務アプリケーション作成に向いていますね。

私はいろいろなフリーソフト等を使ってみましたがやはり.NET Compact Frameworkで作られたソフトの起動の遅さにはいらいらさせられます。本稿ではC++とWin32APIを使用して高速なプログラムを開発したいと思います。 


導入

まずは環境を構築しましょう。
必ず必要になるのが以下のソフトウェアです。

Microsoft Visual Studio 2005 Standard
または
Microsoft Visual Studio 2008 Professional

WindowsMobileの開発はVisual Studio 2005 であれば比較的安価なStandard版で開発できますが、Visual Studio 2008 よりProfessionalからの対応となっています。

Visual Studio 2005 Standard はアップグレード版で推定小売価格19,800円前後、それに対しVisual Studio 2008 Professionalはアップグレード版でも64,800円とかなり高価です
個人でフリーソフト等を作りたい方にとってはちょっと敷居が高すぎますね。

Visual Studio 2005 Standard の販売は既に終了しているので、入手できるうちに入手しておきましょう
私はアップグレードの対象製品を持っていたので、Visual Studio 2005 Standard のアップグレード版を購入しました。

Microsoft Visual Studio 2005 Standardを基本に説明していきます。2008の場合も基本的に違いはありません。

そのほか、WindowsMobileのSDKと、エミュレータのイメージが必要です。これらはマイクロソフトより無償提供されていますのでダウンロードしてインストールします。

■インストール手順

・Microsoft Visual Studio 2005 Standard(またはMicrosoft Visual Studio 2008 Professional)をインストール

・Microsoft Visual Studio 2005 SP1をインストール
Microsoft Updateを使用して、SP1をインストールすることが出来ます。

Microsoftから、WindowsMobileの開発環境をダウンロードしてインストールします。
以下の順序でインストールしていきます。

・Microsoft ActiveSync 4.5日本語版
開発用PCとWindowsMobile間で通信するために必要です。現時点での最新版は4.5です。
※WindowsVistaをお使いの方は、ActiveSyncではなく、「WindowsMobileデバイスセンター」をインストールします。
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=9E641C34-6F7F-404D-A04B-DC09F8141141

・Windows Mobile 5.0 Pocket PC SDK
Windows Mobile 開発に必要なSDKをインストールします。
http://www.microsoft.com/downloads/details.aspx?FamilyID=83a52af2-f524-4ec5-9155-717cbe5d25ed&DisplayLang=en

・Windows Mobile 5.0 Emulator Images for Pocket PC - JPN
開発用PCでWindowsMobile5の動作をエミューレーションするために必要です。各国語版があるので日本語版をダウンロード、インストールします。
http://www.microsoft.com/downloads/details.aspx?FamilyID=eec33ae3-c129-4c25-abaa-18e8e842178f&DisplayLang=en

・.NET Compact Framework 2.0 
PC 用の.NET Framework とは別です。.NET Frameworkの「サブセット」になります。
モバイル機器向けに.NET Framework機能を限定したものです。
Windows Mobile 6 SDK のインストールに必須です。
http://www.microsoft.com/downloads/details.aspx?FamilyID=aea55f2f-07b5-4a8c-8a44-b4e1b196d5c0&DisplayLang=ja

・Windows Mobile 6 Professional SDK Refresh
Windows Mobile 6 SDKにはProfessionalとStandardがあります。ターゲットデバイスにより必要なほうをインストールします。ProfessionalがAdvanced W-ZERO3[es]などの、タッチパネルを持ったWM機になります。
ProfessionalとStandardの両方入れておいても別に問題ないので、どちらも入れておくことにします。
http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&DisplayLang=en

・Windows Mobile 6 Professional Images (JPN)
開発用PCでWindows Mobile 6 Professionalの動作をエミューレーションするために必要です。
http://www.microsoft.com/downloads/details.aspx?FamilyID=38c46aa8-1dd7-426f-a913-4f370a65a582&DisplayLang=en

・Windows Mobile 6 Standard SDK Refresh
Standardはタッチパネルを持たず、よりケータイライクなバージョンです。
国内ではソフトバンクのX02HTに搭載されていますね。
http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&DisplayLang=en

・Windows Mobile 6 Standard Images (JPN)
開発用PCでWindows Mobile 6 Standardの動作をエミューレーションするために必要です。
http://www.microsoft.com/downloads/details.aspx?FamilyID=38c46aa8-1dd7-426f-a913-4f370a65a582&DisplayLang=en

・デバイスエミュレータ2.0(日本語版)
Visual Studio 2005には 英語版が付属していますが、日本語版をインストールすることでデバイスエミュレータを日本語で利用できます。英語版でも不都合はありませんが、日本語が良いという方はインストールしてください。
※Visual Studio 2008 Professionalの方は3.0がすでにインストールされているので不要です。
※デバイスエミュレータ3.0がリリースされています。後述の3.0をインストールする場合2.0のインストールは不要です。
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=dd567053-f231-4a64-a648-fea5e7061303

・デバイスエミュレータ3.0(日本語版)
Visual Studio2008に付属しているDevice Emulator 3.0をVisual Studio 2005でも利用できるようになりました。これをインストールすると既にデバイスエミュレータがインストールされている場合3.0に置き換わります。
http://www.microsoft.com/downloads/details.aspx?FamilyID=a6f6adaf-12e3-4b2f-a394-356e2c2fb114&DisplayLang=ja

これで開発環境の準備はOKです。早速Microsoft Visual Studio 2005を起動してみたいところですが・・・

今日はここまでです。

  1. 2008/06/16(月) 23:52:46|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

参考文献

著者名:
出版年:
書名:
出版社:
総ページ数:

著者名:ホーミン, Offisnail
出版年:2008年
書名:Windows Mobileプログラミング徹底理解
出版社:ソフトバンククリエイティブ
総ページ数:416ページ

著者名:粂井 康孝
出版年:2005年
書名:猫でもわかるゲームプログラミング
出版社:ソフトバンク クリエイティブ
総ページ数:448ページ

著者名:赤坂 玲音
出版年:2004年
書名:Windowsゲームプログラミング
出版社:ソフトバンククリエイティブ
総ページ数:432ページ
  1. 2008/06/16(月) 23:33:20|
  2. WindowsMobileではじめるWin32APIプログラミング入門
  3. | トラックバック:0
  4. | コメント:0

RSSフィード

カレンダー

05 | 2008/06 | 07
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 - - - - -

カテゴリー

最近の記事

最近のコメント

最近のトラックバック

月別アーカイブ

ブロとも申請フォーム

この人とブロともになる

ブログ内検索

リンク

このブログをリンクに追加する

メールフォーム

名前:
メール:
件名:
本文:

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。