→OS関連
→COM技術関連
Tips †
- Win32雑学ノート
- セッション−ウィンドウステーション−デスクトップの関連について説明がある
- これらのデスクトップのさらに上位に位置するのがウィンドウステーションである。ウィンドウステーションには、大きく分けて I/O ウィンドウステーションと Non I/O ウィンドウステーションの2種類がある。後述するセッションには高々ひとつだけ I/O ウィンドウステーションが存在できる。 I/O ウィンドウステーションとは、文字通り Input / Output を行うウィンドウステーション。つまり、セッションにはひとつだけ、入力を受付画面に出力することのできるウィンドウステーションがある。先に述べた二つのデスクトップも、この I/O ウィンドウステーションに属する。
- では Non I/O ウィンドウステーションは何のために用意されているのだろう。その答えは「サービス」である。サービスは入出力の必要はない。 Non I/O ウィンドウステーションはセッションにいくつでも存在できる。サービスが動作する LUID に応じて Non I/O ウィンドウステーションが作られ、それぞれ GUI 的に隔離された空間に置かれる。
イベントログ †
- 出力サンプル
char buf[] = "イベントログに記録したいメッセージ";
LPCSTR lpBuf = buf;
hEvent = RegisterEventSource( NULL, "hogehoge" );
if (hEvent != NULL) {
//イベントログ書き込み
bRet = ReportEvent( hEvent, EVENTLOG_ERROR_TYPE, 0, 1, NULL, 1, 0, &lpBuf, NULL);
if ( bRet == FALSE ) {
DWORD err = GetLastError();
LPVOID lpMsgBuf=NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 既定の言語
(LPTSTR) &lpMsgBuf,0,NULL
);
OutputDebugString((LPCSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
}
- 参考サイト:イベントログにメッセージを出力する
Professional User Interface Suite †
DirectX/WPF †
GDI/GDI+ †
gdi++.dll †
小文字→大文字変換 †
システムエラーの際メッセージボックスを出さなくする †
SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
画面のキャプチャ方法三種類 †
Taskbar Progress Control †
ウィンドウハンドルからモジュール名を得る †
Processing Global Mouse and Keyboard Hooks in C# †
SetUpDIxxx関数によるデバイス情報の列挙 †
タスクバーをプログラムから制御する †
デスクトップ上のウィンドウをグリッドに沿って合わせるユーティリティ †
現在ログオンしているユーザの情報を得る †
GetSystemMetricsのパラメータの微妙な違い †
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int nIndex);
const int SM_CXSCREEN = 0;
const int SM_CYSCREEN = 1; //デスクトップ画面全体
const int SM_CXFULLSCREEN =16;
const int SM_CYFULLSCREEN =17; //フルスクリーンにしたときのクライアント領域(ステータスバー分が入らない)
const int SM_CXMAXIMIZED=61;
const int SM_CYMAXIMIZED=62; //フルスクリーンにしたときの全体(タスクバー分が入らない)
ウィンドウの強制前だし要件への対応 †
- ※強制的に前に出てくるウィンドウというのは下品な仕様です。本当にそれが必要か?確認した上で実装すべし
- 単純にSetForegroundWindow APIとかを使うだけではダメである件について
- http://techtips.belution.com/ja/vc/0012/
void SetAbsoluteForegroundWindow(HWND hWnd)
{
int nTargetID, nForegroundID;
DWORD sp_time;
// フォアグラウンドウィンドウを作成したスレッドのIDを取得
nForegroundID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
// 目的のウィンドウを作成したスレッドのIDを取得
nTargetID = GetWindowThreadProcessId(hWnd, NULL );
// スレッドのインプット状態を結び付ける
AttachThreadInput(nTargetID, nForegroundID, TRUE ); // TRUE で結び付け
// 現在の設定を sp_time に保存
SystemParametersInfo( SPI_GETFOREGROUNDLOCKTIMEOUT,0,&sp_time,0);
// ウィンドウの切り替え時間を 0ms にする
SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT,0,(LPVOID)0,0);
// ウィンドウをフォアグラウンドに持ってくる
SetForegroundWindow(hWnd);
// 設定を元に戻す
SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT,0,sp_time,0);
// スレッドのインプット状態を切り離す
AttachThreadInput(nTargetID, nForegroundID, FALSE ); // FALSE で切り離し
}
DLLの関数一覧を得る †
- プログラムで取得するには(プログラムのヘッダ情報から取得)
DLLの関数差し替え †
- 参考資料:http://www.users.gr.jp/blogs/hidori/archive/2005/07/25/14423.aspx
BOOL ReplaceDllProc(
LPCTSTR lpSourceModuleName, // 置換対象の DLL 関数が格納されているモジュールの名前
LPVOID lpCurProc, // 置換対象の DLL 関数のアドレス
LPVOID lpNewProc, // 新しい DLL 関数のアドレス
HMODULE hNewProcModule // 新しい DLL 関数が格納されているモジュールのハンドル
)
{
ULONG ulSize = 0;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR)
::ImageDirectoryEntryToData(hNewProcModule, TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
if (!pImportDesc)
{
return FALSE;
}
for (; pImportDesc->Name; pImportDesc++)
{
LPCTSTR lpModName = (LPCTSTR) ((PBYTE) hNewProcModule + pImportDesc->Name);
if (!_tcsicmp (lpModName, lpSourceModuleName))
{
break;
}
}
if (!pImportDesc->Name)
{
return FALSE;
}
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) ((PBYTE) hNewProcModule + pImportDesc->FirstThunk);
for (; pThunk->u1.Function; pThunk++)
{
LPVOID* ppfn = (LPVOID*) &(pThunk->u1.Function);
BOOL fFound = (*ppfn == lpCurProc);
if (fFound)
{
::WriteProcessMemory (::GetCurrentProcess(), ppfn, &lpNewProc, sizeof(lpNewProc), 0);
return TRUE;
}
}
return FALSE;
}
DLLの共有セグメント(C++) †
DLL のソースコードに
#pragma comment(linker,"/section:SHARED,rws")
#pragma data_seg("SHARED")
HWND hwndOwner = 0;
HHOOK hhk = 0;
#pragma data_seg()
のように記述。
#pragma data_seg は、#pragma data_seg で括られた区間がデータセグメントであること、セクション名が "SHARED" であることを示し
#pragma comment ディレクティブは、リンカに対する指示で、"SHARED" と名前付けられたセクションが「読み書き可能、共有」の属性を持つことを指定
この2つの記述により、変数 hwndOwner と hhk は、この DLL をロードしたプロセス間で共有される。
なお、共有する変数は
HWND hwndOwner = 0;
のように必ず初期化すること。
これを忘れると、変数が共有されません。