Microsoft Windowsは、C言語やC++から呼び出すことができるWindows APIを提供している。Windows APIを呼び出すことにより、Microsoft Windowsが持つ機能をプログラミング言語から利用することができる。
Windowsの.libファイルには、静的ライブラリとインポートライブラリの2種類の形式がある。静的ライブラリは、必要に応じて取り込まれるコードが入っていて、Linux における.aファイルに似ている。インポートライブラリは、特定の識別子が不正ではなく、DLLがロードされた時点で存在することを保証するためだけに使われる。
Win16 API GetVersion または Win32 API GetVersionEx でWindowsのバージョン情報を取得することができる。
Windowsのバージョン | メジャーバージョン番号 | マイナーバージョン番号 |
---|---|---|
Windows 3.1 | 3 | 1 |
Windows NT 3.5 | 3 | 5 |
Windows 95 | 4 | 0 |
Windows NT 4.0 | 4 | 0 |
Windows 98 | 4 | 1 |
Windows 98 SE (Second Edition) | 4 | 1 |
Windows Me (Millennium Edition) | 4 | 9 |
Windows 2000 | 5 | 0 |
32ビット版 Windows XP 各エディション | 5 | 1 |
Windows Server 2003 | 5 | 2 |
Windows XP x64 Edition | 5 | 2 |
Windows Vista | 6 | 0 |
Windows Server 2008 | 6 | 0 |
Windows 7 | 6 | 1 |
バージョン情報をメモリ上のプロセスから直接取得することはできません。アプリケーションのバージョン情報を取得するには,モジュールのファイルに含まれるリソースから取得します。この手順について,以下に示します。
アプリケーションでファイルのドロップを行えるようにするには,あらかじめファイルのドロップの受け入れ許可をしておきます。これは,Windows API の DragAcceptFiles にて行います。
アプリケーションに対してファイルのドラッグ&ドロップを行うと,ウィンドウメッセージWM_DROPFILESが通知されます。このときのwParamの値はドロップ構造体のハンドルです。
hDrop = (HANDLE)wParam;
ドロップされたファイルのパス名を取得するには Windows API DragQueryFileを用います。その引数として,ドロップ構造体のハンドル(ウィンドウメッセージWM_DROPFILES通知時のwParamの値)を必要とします。
ドロップされた位置を取得するには,Windows API DragQueryPointを用います。その引数として,ドロップ構造体のハンドル(ウィンドウメッセージWM_DROPFILES通知時のwParamの値)を必要とします。
ドロップされたファイルのファイル名転送用のバッファを解放するには,Windows API DragFinishを用います。その引数として,ドロップ構造体のハンドル(ウィンドウメッセージWM_DROPFILES通知時のwParamの値)を必要とします。
WINDOWSX.Hで定義されているWM_DROPFILESクラッカーに関する定義を以下に示します。
void Cls_OnDropFiles(HWND hwnd, HDROP hdrop);
#define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) ((fn)((hwnd), (HDROP)(wParam)), 0L)
#define FORWARD_WM_DROPFILES(hwnd, hdrop, fn) (void)(fn)((hwnd), WM_DROPFILES, (WPARAM)(HDROP)(hdrop), 0L)
16ビットWindowsでは,DLLは自分のデータセグメントを持っています。 このデータセグメントは,DLLが必要とするすべての静的変数,グローバル変数とDLL自身のプライベートローカルヒープを収めています。DLL関数を呼び出したプロセスがどれであっても,DLLは自分のローカルヒープを使えるため,DLLローカルヒープは複数のプロセス間でのデータ共有を簡単に実現するための手段として利用できました。
しかし,Win32のDLLには,ローカルヒープが与えられません。また,DLLによって割り当てられたグローバル変数,静的変数もDLLの複数のマッピングの間では共有されません。このため,DLLの複数インスタンス間で共有するデータは,共有セクションに配置します。
Sharedという新しい独自セクションを作成して、初期化済みデータ変数をこのセクションに配置する例を次に示します。
#pragma data_seg("Shared")
TCHAR gszSystemDir[SIZE_WORK_BUF] = "";
#pragma data_seg()
そして,リンカに対して,変数を共有するセクション名をリンカのオプションスイッチで指定します。
/SECTIONのあと,:で区切って属性を変更するセクションの名前を指定します。属性として指定できるのはR(Read),W(Write),S(Shared),E(Execute)であり,複数指定できます。
Sharedセクションを読み書き可能な共有セクションとして指定する例を次に示します。
Visual C/C++でフォルダ内のファイルを検索するには、3通りの方法がある。
ウィンドウの破棄に必要な様々な終了処理を行う。そしてWM_DESTROYとWM_NCDESTROYメッセージをウィンドウに送る。
DragAcceptFiles関数は、ウィンドウがドロップしたファイルを受け入れるかどうかを登録する関数である。
VOID DragAcceptFiles(
HWND hWnd,
BOOL fAccept
);
この関数は値を返さない。
fAcceptパラメータをTRUEに設定してDragAcceptFilesを呼び出したアプリケーションは、ファイルマネージャからのWM_DROPFILESメッセージを処理することができると認識されています。
DragFinish関数は、Windowsがアプリケーションにファイル名を転送するために確保したメモリを解放する。
VOID DragFinish(
HDROP hDrop
);
この関数は値を返さない。
DragQueryFile関数は、ドロップしたファイルのファイル名を取得する関数である。
UINT DragQueryFile(
HDROP hDrop,
UINT iFile,
LPTSTR lpszFile,
UINT cch
);
この関数がファイル名をバッファにコピーする場合、戻り値はコピーされた文字数であり、終端のNULL文字は含まれない。
インデックス値が 0xFFFFFF の場合は、ドロップしたファイルの数を返す。
インデックス値が0からドロップされたファイルの総数の間で、lpszFileバッファアドレスがNULLの場合、戻り値はバッファの必要サイズ(文字数)です(終端NULL文字は含まれません)。
DragQueryPoint関数は、ファイルがドロップされたときのマウスポインタの位置を取得する関数である。
BOOL DragQueryPoint(
HDROP hDrop,
LPPOINT lppt
);
ドロップがウィンドウのクライアント領域で発生した場合、戻り値は TRUE であり、そうでない場合は FALSE である。
DragQueryPoint関数は、ユーザーがマウスの左ボタンを離したときのマウスポインタの座標でPOINT構造体を埋める。座標が返されるウィンドウは、WM_DROPFILESメッセージを受信したウィンドウである。
ファイルバージョン情報の取得。
BOOL GetFileVersionInfo(LPTSTR pFileName, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
関数が正常に終了した場合は,0以外の値を返す。それ以外の場合は0を返し,ファイルが存在しないか,またはdwHandleパラメータが無効であることを示す。
バージョン情報を取得できるか判定する。
DWORD GetFileVersionInfoSize(LPTSTR pFileName, LPDWORD lpdwHandle);
関数が正常に終了した場合は,バージョン情報の保持に必要なバッファサイズをバイト単位で返す。ファイルやバージョン情報が見付からなかった場合,またはMS-DOSエラーが発生した場合は,NULLを返す。
モジュールがロードされる実行可能ファイルの完全パスとファイル名を取得する。
DWORD GetModuleFileName(HMODULE hModule, LPTSTR pFileName, DWORD dwSize);
関数が正常に終了した場合,戻り値は指定されたバッファにコピーされた文字列の長さをバイト単位で示す。それ以外の場合,0を返す。
.iniファイル(初期化ファイル)からInt値を読み込む。
UINT GetPrivateProfileInt(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
INT nDefault,
LPCTSTR lpFileName
);
指定したキーに対応する値
.iniファイル(初期化ファイル)からString値を読み込む。
[section]
key=value
key=value
[section]
key=value
DWORD GetPrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPTSTR lpReturnedString,
DWORD nSize,
LPCTSTR lpFileName
);
バッファに格納された文字数
現在実行中のオペレーティングシステムのバージョンに関する拡張情報を取得する。
BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInformation);
成功したらTRUE、失敗したら FALSEを返す。
PostQuitMessage()はWM_QUITメッセージをポストする。WM_QUITメッセージを受け取ると、GetMessage()はFALSEを返して、メッセージループが終了する。
通常、WM_DESTROYメッセージ対する応答としてPostQuitMessage関数を使う。
バージョン情報値の問い合わせを行う。
BOOL VerQueryValue(const LPVOID pBlock, LPTSTR lpSubBlock, LPVIOD *lplpBuffer, PUINT puLen);
指定されたブロックが存在してバージョン情報が利用できる場合は,0以外の値を返す。puLenが0の場合は,指定されたバージョン情報名に対する値を使用することができない。指定された名前が存在しない場合またはpBlockが指すリソースが無効の場合には0返す。
.iniファイル(初期化ファイル)に値を書き込む。
BOOL WritePrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpString,
LPCTSTR lpFileName
);
成功したら0以外、失敗したら0が返る。失敗した場合、GetLastErrorで情報を得ることができる。
OSVERSIONINFOはOSのバージョン情報が格納されている構造体である。
typedef struct _OSVERSIONINFO{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[128];
} OSVERSIONINFO;
dwOSVersionInfoSize
GetVersionEx
関数を呼び出す前に,sizeof(OSVERSIONINFO)
をセットしておかなければならない。dwMajorVersion
dwMinorVersion
dwBuildNumber
dwPlatformId
szCSDVersion
POINT構造体は、点のx座標とy座標を定義する。
typedef struct tagPOINT { // pt
LONG x;
LONG y;
} POINT;
DefWindowProc() がWM_CLOSEウィンドウメッセージを受け取ると、DestroyWindow() を呼び出す。
OSのシャットダウンで閉じられようとしている。
パラメータ | 説明 |
---|---|
wParam | 0:セッションが終了していないとき(WM_QUERYSESSIONでFALSEが返されたととき) 1:セッションが終了するとき |
lParam | 0:シャットダウンしようとしているとき 1:ログオフしようとしているとき |
システムがシャットダウンしようとする際、WM_QUERYSESSIONメッセージがトップレベルウィンドウに対して送られてくる。 ここで、アプリケーションが終了できる状態であればTRUEを返す。そうでなければFALSEを返す。
WM_QUERYSESSIONメッセージに対してすべてのアプリケーションがTRUEを返した場合、システムはシャットダウンできる状態にあるとみなしてシャットダウンを続行する。 システムはすべてのトップレベルウィンドウに対してWM_ENDSESSIONメッセージを送信し、シャットダウンを会することを知らせる。 アプリケーションではこのメッセージを受信した時点で終了処理を行わなければならない。
m.WParam.ToInto32() == SC_CLOSE
×ボタン、コントロールメニューの「閉じる」、コントロールボックスのダブルクリック、Alt + F4 などにより閉じられようとしている。
DefWindowProc() がこれを受け取ると、ウィンドウプロシージャにWM_CLOSEを送る。
マネージドCプログラムを記述する場合、特別な手続きは必要ない。
#include <stdio.h>
void main()
{
printf("Hello world!");
}
ただし、C言語の標準ライブラリはマネージド・コードではない。したがって、C言語プログラムから標準ライブラリを呼び出した場合、マネージド・コードからアンマネージド・コードを呼び出すことになる。
マネージド・コードからアンマネージド・コードのライブラリを呼び出すには、PInvoke (Platform Invocation) と呼ばれるサービスを利用する。PInvokeサービスを使用してアンマネージド・コードのライブラリを呼び出すには、System.Runtime.InteropServices.DllImport属性を使用して、呼び出す関数を宣言する。
あらかじめSystem.Runtime.InteropServicesネームスペースの使用を宣言しておけば、名前空間を明示的に修飾しなくともよい。
Win32 APIのライブラリ user32.dll はアンマネージド・コードである。マネージドC++プログラムからWin32 API (MessageBoxA) を呼び出す例を示す。
using System;
class HelloWorld {
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int
MessageBoxA(int hWnd, String lpText, String lpCaption, uint uType);
static void Main() {
MessageBoxA(0, "Hello World!", "sample", 0);
}
}
または
using System;
using System.Runtime.InteropServices;
class HelloWorld {
[DllImport("user32.dll")]
public static extern int
MessageBoxA(int hWnd, String lpText, String lpCaption, uint uType);
static void Main() {
MessageBoxA(0, "Hello World!", "sample", 0);
}
}