Programmers Room Tips集 API編 更新[2000.06.03]

Contents

1.システムダウンの方法 [1999.5.30]
2.Windowを中央に表示させる [1999.9.15]
3.一つのタスク内の排他処理 [1999.12.12] 
4.異なるタスク間の排他処理(2重起動防止) [1999.12.12]
5.Windowsのバージョンの取得 [2000.06.03]New!!

・・・初心者
・・・中級者
・・・上級者

1.システムダウンの方法 [1999.5.30]

「API、ExitWindowsEx() を使用する」

ExitWindowsEx( UINT uFlags, DWORD dwReserved );

uFlags の内容
EWX_FORCE : 強制終了
EWX_LOGOFF : アプリケーションを終了してログオフ
EWX_POWEROFF : 電源を切れる状態にする
EWX_REBOOT : 再起動する
EWX_SHUTDOWN : システムダウン(EWX_POWEROFFと同一内容と考える)

dwReserved : 予備。常時0

2.Windowを中央に表示する  [1999. 9.15]

通常BCBで中央に表示させるなら、フォームの「Position」プロパティを"poDesktopCenter"に設定するのみです。

さて、これをAPIのみで記述する場合はどうなるでしょう?以下のようになります。
記述場所は、BCB や VC++なら クラスのプロパティ(たとえば上記)やメソッドで簡単に設定できるわけですから、特に説明しません。

DialogベースのAPIのみのアプリケーションの場合は、ダイアログの処理メッセージループに以下の用に記述します

BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch( uMsg )
    {
        case WM_INITDIALOG:
            // Dialogの初期化。
            {
            // Window Positoionを中心に
            RECT tRect;
            RECT tMyRect;
            GetWindowRect(GetDesktopWindow(), &tRect);
            GetWindowRect(hwndDlg, &tMyRect);
            int nWidth = tMyRect.right - tMyRect.left;
            int xs = (tRect.right / 2) - (nWidth / 2);
            int nHeight = tMyRect.bottom - tMyRect.top;
            int ys = (tRect.bottom / 2) - (nHeight / 2);
            MoveWindow(hwndDlg, xs, ys, nWidth, nHeight, false);
            }
            return TRUE;
        case WM_COMMAND:

GetWindowRect()は指定されたウィンドウのサイズを取得します。引数のウィンドウハンドルにGetDesktopWindow()はデスクトップのハンドルを取得する関数を設定することによりデスクトップの四隅の座標を取得することになるわけです。

次に自分のWindowの座標を取得して、あとはWindowの位置を移動する関数にMoveWindowに渡すWindowが中心にきたときの左上の座標とWindowの幅と高さをベタベタに四則演算で算出し設定します。

 

3.一つのタスク内の排他処理  [1999.12.12]

一つのタスク(実行ファイル)内において排他処理をおこなうためには、CriticalSection(クリティカルセクション)を使用します。

排他処理とは、ある処理が処理している間は、他の処理は全て待ちになることで、Critical Sectionは処理が同時に実行される、スレッドアプリケーションにおいて、簡単に排他処理を実現する方法です。

Windows APIの構造体、CRITICAL_SECTIONのオブジェクトを定義し、利用するのですが、このオブジェクトに名前がついている訳ではないので、同一のオブジェクトを全ての個所で使用することになります。よって、グローバル変数とするか、またはクラスがあるなら、タスク内で共通に参照できるクラス(VCならCWinAppの派生クラスであるメインクラス。BCBならばメインのフォームクラス)のメンバとして定義すると良いでしょう。

以下はグローバルで定義した例です。


CRITICAL_SECTION g_Lock; 
// クリティカルセクションをグローバルで宣言

// アプリケーションの初期化を行う関数。
// (クラスの場合、VCがCWinAppの派生クラスのInitInstance
//    BCBならメインフォームのFormCreateと同じ)
int InitApp()
{
        // (その他もろもろの処理)
        //            :

        // クリティカルセクションを初期化する。
        InitializeCriticalSection(&g_Lock);

        //            :
}

// アプリケーションの終了処理を行う関数。
// (クラスの場合、VCがCWinAppの派生クラスのExitInstance
//    BCBならメインフォームのFormDestroyと同じ)
int EndApp
{
        //            :

        // クリティカルセクションを削除する
        DeleteCriticalSection(&g_Lock);

        //            :
}

// イベント実験用スレッド
// (スレッドだからこの関数が複数同時に起動する)
int TestThred(LPVOID pParam)
{
        // クリティカルセクションに入る
        // 他のスレッドがクリティカルセクションにはいっている間
        // ここで止まって待つ。
        EnterCriticalSection(&g_Lock);

        // (この間何らかの同時に走ってほしくない、処理
        // (例えば共通のファイル操作)などが入る。)

        // クリティカルセクションを抜ける
        // 他に待っている個所があれば、そちらが動き出す。
        LeaveCriticalSection(&g_Lock);

        return( 0 );
}

 

4.異なるタスク間の排他処理(2重起動防止)  [1999.12.12]

上記Critical Sectionの場合、同一のタスク(プロセス・実行ファイル)内でしか実行できませんが、異なるタスク間で排他を行う場合、MutexObjectを利用します。

用途は、ファイルやDBの一連の処理(「一連」と書いたのは、ファイルやDBそのものには、通常排他するための手法がついているから)や、2重起動防止などに使用します。

以下の例は、2重起動を防止する処理を、BCBのメインルーチンに入れた例です。VCの場合はInitInstance()に同様にいれてやればよいでしょう。
Mutexの場合は、同一のオブジェクトではなく、名前を付けて作成して(この例では「WatashiNoApp」)同一の名前が宣言されているかチェックして、存在すれば終了するという仕組みです。


WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        try{
               
// 二重起動防止。Mutexを開いてみる。
                HANDLE hMutex;
                hMutex = OpenMutex(MUTEX_ALL_ACCESS, false,
                        
"WatashiNoApp");

               
//0では無いということは既に作成されているのだから終了する
                if( hMutex != 0 ){ 

                        CloseHandle(hMutex);
// 開いたものは閉じる
                        return(
1); //終了
                }
                else
// 開け無いということは、まだ存在していない。
                        hMutex = CreateMutex(NULL, true,
"WatashiNoApp");

                Application->Initialize();
                               
// (中略・この辺は自動生成されるところ)
                Application->Run();

                ReleaseMutex(hMutex);
//ミューテクス解除
        }
        catch (Exception &exception){
                Application->ShowException(&exception);
        }
        return(
0);
}

 

5.Windowsのバージョン取得  [2000.06.03]  

Windowsのバージョンを取得する場合APIの

BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInformation);

を使用します。

引数は以下の構造体を宣言し、アドレスを渡します。

  typedef struct _OSVERSIONINFO{
          DWORD dwOSVersionInfoSize; 
         DWORD dwMajorVersion;
          DWORD dwMinorVersion;
          DWORD dwBuildNumber; 
         DWORD dwPlatformId;
          TCHAR szCSDVersion[ 128 ];
  } OSVERSIONINFO;   

構造体OSVERSIONINFOの各メンバの内容は、以下のとおりです。

dwOSVersionInfoSize

この構造体のサイズです。関数をコールする前に
sizeof(OSVERSIONINFO) を代入しておきます。(しないと誤動作します。)

dwMajorVersion

メジャーバージョン
Windows NT version 3.51は 3
NT version 4.0は4.
Windows98も4

dwMinorVersion

マイナバージョン
Windows NT version 4.0 は0.
Windows98SEは10 (0a(H))

dwBuildNumber

Windows NTはビルド番号が入ります。

Windows 95: は下位バイトにビルド番号が入り、上位ワードにメジャーバージョンとマイナーバージョンが入ります。

dwPlatformId

プラットフォームの番号が入ります。このメンバには次に示す値のうちの1つが指定されてきます。
プラットフォーム
VER_PLATFORM_WIN32s Windows 3.1.のWin32s
VER_PLATFORM_WIN32_WINDOWS Windows 95または Windows 98.のWin32
Windows 95はdwMinorVersion が0. Windows 98はdwMinorVersion が0より大きくなります
VER_PLATFORM_WIN32_NT Windows NT.のWin32

szCSDVersion

OSに関する追加情報が、\0で終わる文字列で格納されます。

Windows NTはサービスパックがインストールされている場合に。 "Service Pack 3"のように設定されます。

:OSのメジャーバージョンとマイナーバージョンをメッセージボックスで表示する。

        OSVERSIONINFO	tOSVersion;

        tOSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        GetVersionEx(&tOSVersion);
        CString Str;
        Str.Format("Ver.=%x.%x."), tOSVersion.dwMajorVersion, tOSVersion.dwMinorVersion);
        MessageBox(Str);

 


[TOPへもどる] [Soft Page TOPへもどる] [ProgramerS Room Topに戻る] [このページのTop]