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

小文字→大文字変換

  • いわゆるToUpper()に相当する CharUpperBuff
    http://msdn.microsoft.com/ja-jp/library/cc410688.aspx

システムエラーの際メッセージボックスを出さなくする

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の関数一覧を得る

  • コマンドで取得するには(dumpbinを使う)
    dumpbin /exports XXXX.dll > hoge.txt
    • export以外も含め全部出す場合は、リンカのオプションに/MAPを付ける。
    • そうすると出力先ディレクトリに*.mapファイルが生成される。
    • C++の場合、コンパイラが付けた修飾名で関数が出力される。
    • C++の関数でDEFファイルを作るときに手助けになるはず。

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;

のように必ず初期化すること。 これを忘れると、変数が共有されません。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-10-01 (月) 23:31:19 (3125d)