今回は、レジストリ操作を扱います。アプリケーションを起動した回数を表示するようにします。
初回起動時はレジストリに保存したというメッセージボックスを表示させます。
レジストリ エディターで確認すれば、保存されていることがわかります。
WM_PAINTメッセージ - インコのWindowsSDK で作成したソースを修正します。
流れ
WM_CREATE
1.RegCreateKeyEx()でレジストリキーを作成。すでにレジストリキーがある場合は、レジストリキーをオープン。
LONG RegCreateKeyEx( HKEY hKey, // キーのハンドル PCTSTR pszSubKey, // サブキーの名前 DWORD Reserved, // 0固定 PTSTR pszClass, // クラス名(空白を指定) DWORD dwOptions, // オプション REGSAM samDesired, // セキュリティのオプション PSECURITY_ATTRIBUTES psa, // セキュリティ属性 PHKEY phkResult, // ハンドルを格納する変数 PDWORD pdwDisposition );
hKey | キーのハンドル HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERSなどを指定 Windows Vista以降は、管理者として実行しないと、HKEY_CLASSES_ROOT、HKEY_LOCAL_MACHINE には、書き込めません。 |
|
pszSubKey | 作成またはオープンするサブキーの名前 | |
Reserved | 0固定 | |
pszClass | クラス名(空白を指定) | |
dwOptions | オプション | |
REG_OPTION_NON_VOLATILE | システムを再起動しても情報が残るキー | |
REG_OPTION_VOLATILE | システムを再起動すると情報が残らないキー | |
samDesired | セキュリティのオプション | |
KEY_ALL_ACCESS | 全許可 | |
psa | セキュリティ属性 取得したハンドルの子プロセスへの継承を許可する場合以外は、NULL(0) |
|
phkResult | 作成またはオープンされたキーのハンドルを、格納するための変数のアドレス | |
pdwDisposition | キーが新しく作成されたかどうかを示す値を、格納する変数のアドレス NULLを指定しなかった場合は、下記の値が変数に保存 |
|
KEY_QUERY_VALUE | 指定されたキーが存在しなかったため、キーが新しく作成 | |
REG_OPENED_EXISTING_KEY | 指定されたキーが既に存在しており、そのキーがオープンされた |
2.RegQueryValueEx()でレジストリキーから、指定した値のデータを取得。
RegQueryValueEx()を2回呼んでいます。
1回目はpDataパラメータをNULLにすることで、バッファサイズをいったん取得しています。
2回目に、取得したバッファサイズを指定して、データを格納しています。
LONG RegQueryValueEx( HKEY hKey, // キーのハンドル PCTSTR pValueName, // 値の名前 PDWORD pReserved, // NULL(0)固定 PDWORD pType, // データタイプを格納する変数 PBYTE pData, // データを格納するバッファ PDWORD pcbData // バッファサイズを入れた変数 );
3.RegCloseKey()で、レジストリキーを閉じます。
LONG RegCloseKey( HKEY hKey // キーのハンドル );
4.RegOpenKeyEx()で、レジストリキーを開きます。
RegCreateKeyEx()と違い、レジストリキーを作成することはできません。
LONG RegOpenKeyEx( HKEY hKey, // キーのハンドル PCTSTR pSubKey, // オープンするサブキーの名前 DWORD ulOptions, // NULL(0)固定 REGSAM samDesired,// セキュリティのオプション PHKEY phkResult // ハンドルを格納する変数のアドレス );
5.RegSetValueEx()で、レジストリキーを保存します。
LONG RegSetValueEx( HKEY hKey, // キーのハンドル PCTSTR pValueName, // 値の名前 DWORD Reserved, // NULL(0)固定 DWORD dwType, // データのタイプ CONST BYTE *pData, // データバッファのアドレス DWORD cbData // データサイズ );
dwType (データのタイプ)は次を指定します。
REG_SZ | 文字列 |
REG_DWORD | 32ビット数値 |
REG_QWORD | 64ビット数値 |
ソースコードの入力
ソースコードは下記のように入れてください。
test.cpp
#include <windows.h> #include <tchar.h> #include <stdio.h> #include "resource.h" #define SUB_KEY TEXT("Software\\my_test") // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; MyRegisterClass(hInstance); // アプリケーションの初期化を実行します: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } // メイン メッセージ ループ: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } // // 関数: MyRegisterClass() // // 目的: ウィンドウ クラスを登録します。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL , IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HP); wcex.lpszClassName = TEXT("HP"); wcex.hIconSm = LoadIcon(NULL , IDI_APPLICATION); return RegisterClassEx(&wcex); } // // 関数: InitInstance(HINSTANCE, int) // // 目的: メイン ウィンドウを作成します。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(TEXT("HP"), TEXT("HP"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 関数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: メイン ウィンドウのメッセージを処理します。 // // WM_CREATE - ウインドウ作成時の処理 // WM_COMMAND - アプリケーション メニューの処理 // WM_PAINT - メイン ウィンドウの描画 // WM_DESTROY - 中止メッセージを表示して戻る // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR str[1024]; LONG lResult; DWORD dwDisposition; static HKEY hKeyResult; DWORD dwData; DWORD dwType = REG_DWORD; static DWORD dwPostalNum; switch (message) { case WM_CREATE: /* レジストリキーを作成 */ lResult = RegCreateKeyEx(HKEY_CURRENT_USER, SUB_KEY, NULL, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyResult, &dwDisposition); if (lResult == ERROR_SUCCESS) { if (dwDisposition == REG_CREATED_NEW_KEY) { MessageBox(NULL, TEXT("キーが存在しないので新たに作成しました"), TEXT("OK"), MB_OK); } } /* レジストリの値を取得 */ RegQueryValueEx(hKeyResult, TEXT("data00"), NULL, &dwType, NULL, &dwData); RegQueryValueEx(hKeyResult, TEXT("data00"), NULL, &dwType, (LPBYTE)&dwPostalNum, &dwData); /* レジストリのキーを閉じる */ RegCloseKey(hKeyResult); dwPostalNum++; /* レジストリのキーを開く */ RegOpenKeyEx(HKEY_CURRENT_USER, SUB_KEY, NULL, KEY_ALL_ACCESS, &hKeyResult); /* レジストリに保存 */ RegSetValueEx(hKeyResult, TEXT("data00"), 0, REG_DWORD, (CONST BYTE*)&dwPostalNum, sizeof(dwPostalNum)); /* レジストリのキーを閉じる */ RegCloseKey(hKeyResult); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 選択されたメニューの解析: switch (wmId) { case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); _stprintf_s(str, 255, TEXT("%d 回目の起動です。"), dwPostalNum); TextOut(hdc, 10, 10, str, _tcslen(str)); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
上記の太線で示している箇所のみ追加です。
resource.h (変更なし)
#define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDC_HP 109
test.rc リソースファイル (変更なし)
#include "resource.h" ///////////////////////////////////////////////////////////////////////////// // // メニュー // IDC_HP MENU BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "アプリケーションの終了(&X)", IDM_EXIT END POPUP "ヘルプ(&H)" BEGIN MENUITEM "バージョン情報(&A)...", IDM_ABOUT END END