キーワード:ハードコピー 解除
WindowsでPrintScreenを押すとスクリーンショットがクリップボードへコピーされますね。
Altキーを押したままPrintScreenを押すと、現在のウィンドウのみのスクリーンショットが取れます。
※ノートPCなんかではFnキーを押さないとPrintScreenとして動作しないものがあります。

このPrintScreenを押した時の動作をプログラミングにより自分で色々と変更したいと思った時にやった事をちょっと(ちょっとじゃないかも)書いてみたいと思います。
VC++でWinAPIを使ったやり方になります。

まず最初に思いついた事は、グローバルフックでPrintScreenキーのメッセージを横取りする事。
ただ、今回の場合はホットキーで十分事足りるので扱いが簡単なホットキーを使う事にしました。

ホットキーの登録はこんな感じ・・・

// PrintScreenを押した時
::RegisterHotKey(hWnd, 10, 0, VK_SNAPSHOT);

// Alt+PrintScreenを押した時
::RegisterHotKey(hWnd, 11, MOD_ALT, VK_SNAPSHOT);

※RegisterHotKeyで登録したホットキーは使わなくなったら必ずUnregisterHotKeyで解除を行います。

こんな感じでね・・・

::UnregisterHotKey(hWnd, 10);
::UnregisterHotKey(hWnd, 11);

こうする事で指定したウィンドウにそのPrintScreen(Alt+PrintScreen)が押されたらWM_HOTKEYという
ウィンドウメッセージが飛んできますのでそいつを捕まえてコードを書きます。

WM_HOTKEYでは、RegisterHotKeyで指定したホットキーの識別子がWPARAMに入ってきます。
上記の例でいくと、PrintScreenでは10、Alt+PrintScreenでは11を指定しています。
まぁ、この値は#defineしといた方がいいですが例なので直接書いてます。
なので判定としては

if(wParam == 10){
    // PrintScreenが押された時の処理
}else if(wParam == 11){
    // Alt+PrintScreenが押された時の処理
}

みたいに書けます。

じゃあPrintScreenによるスクリーンショットを無効化するか!
と思った場合、クリップボードをクリアしてあげればいいと思ってましたが、
どうやらホットキーとしてキーのイベントを奪ってしまうとそもそもスクリーンショットが
クリップボードへコピーされなくなっていました。
つまり、PrintScreenキーをホットキーとして登録しただけで、PrintScreenキーによる
スクリーンショットが無効化されてしまいました・・・

じゃあPrintScreenキーを押した時ログを残してスクリーンショットは通常通りやりたい!
・・・となった時、どうすればよいか?
スクリーンショットの処理を自分で書くしかないですね。
コードがアレですが、こんな感じで関数化してみました。

// スクリーンショットを取る
bool ScreenShot(HWND hWnd)
{
    // スクリーンサイズ
    int x = ::GetSystemMetrics(SM_CXSCREEN);
    int y = ::GetSystemMetrics(SM_CYSCREEN);
    int x1 = 0, y1 = 0;

    if(hWnd != NULL){
        // Alt+PrintScreenだったら作業中のウィンドウのみを取る
        WINDOWINFO wi;
        ::ZeroMemory(&wi, sizeof(wi)); // ねんのため
        wi.cbSize = sizeof(WINDOWINFO);
        if(!::GetWindowInfo(hWnd, &wi)) return false;
        x = wi.rcWindow.right - wi.rcWindow.left;
        y = wi.rcWindow.bottom - wi.rcWindow.top;
        x1 = wi.rcWindow.left;
        y1 = wi.rcWindow.top;
    }

    HDC hdc = ::GetDC(NULL);
    if(hdc == NULL) return false;
    HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, x, y);

    // エラー判定用
    bool bSuccess = (hBitmap != NULL);

    // ここから先は成功したかを判定しながら進む。

    // メモリデバイスコンテキストを作成
    HDC hdcMem;
    if(bSuccess){
        hdcMem = ::CreateCompatibleDC(hdc);
        bSuccess = (hdcMem != NULL);
    }

    // メモリデバイスコンテキストを選択
    HGDIOBJ hgdiobj;
    if(bSuccess){
        bSuccess = ((hgdiobj=::SelectObject(hdcMem, hBitmap)) != NULL);
    }

    // メモリデバイスコンテキストへビットマップを転送
    if(bSuccess){
        bSuccess = (::BitBlt(hdcMem,0,0,x,y,hdc,x1,y1,SRCCOPY) != 0);
    }

    // クリップボードへコピー
    if(bSuccess && ::OpenClipboard(NULL)){
        bSuccess = (::EmptyClipboard() != 0);
        if(bSuccess) bSuccess = (::SetClipboardData(CF_BITMAP, hBitmap) != NULL);
        ::CloseClipboard();
    }else bSuccess = false;

    // 後片付け
    if(hgdiobj != NULL) ::SelectObject(hdcMem, hgdiobj);
    if(hdcMem != NULL) ::DeleteDC(hdcMem);
    if(hBitmap != NULL) ::DeleteObject(hBitmap);
    if(hdc != NULL) ::ReleaseDC(hWnd, hdc);

    return bSuccess;
}

引数のhWndは見てのとおりスクリーンショットを取りたいウィンドウを指定します。
NULLを指定すると画面全体となります。
現在のウィンドウを取得するのにGetForegroundWindow()で取得したウィンドウを
使う事を想定してますが、問題ないすかね?
あと、戻り値はtrueが成功、falseが失敗です。

WinAPIと言っておきながらC言語ではなくC++の文法で書いてます。
C言語で書く場合は、::を外してboolをBOOL、trueをTRUE、falseをFALSEにして変数の定義をとりあえず関数の先頭に持ってくればいいんじゃないすかね。(適当)

実際に動かしたものからちょっと変更してますので
コンパイルが通らない時やうまく動かない時は自分で治してくださいw
間違いを指摘してもらえればありがたく修正しますw

また、これはマルチモニタの事は考慮してません。
マルチモニタの場合、おそらくプライマリディスプレイしか情報が取れません。。。
対応させるならEnumDisplayDevicesあたりを使う必要があるのかな?

今回も天草とはまったく関係ない話題でしたが、まぁ書くだけいいか、と割り切って書きましたw
おそらく知っている人も多いかと思いますが、ハードコピーの方法を書きます。
他の記事でも同じですが、知ってる人は見てもためになりませんw
(そもそもためになってるのかも疑問ですがwww)

ハードコピーは出力情報をそのまま見れる形で保存したものです。

わかりにくいですね、出力情報=画面と考えてください。
ようはPCなんかの画面をキャプチャしてそのまま画像にして
保存したり印刷したりする事です。

画面コピーとかスクリーンショットとか言ったりもします。
好きなように呼んでいいんじゃないですかねw

ではそのハードコピーなんですがどうやればいいんでしょうか?
ここではWindowsとして話を進めます。
LinuxのGUI環境でも同じ方法でできたと思います。
(Macは使った事ないので知りません。どっかで[CMD]+[F7]か[F8]と見たような気がする)

まず、キーボードを見てください。
キーボードにもよりますが、右上付近に[PrintScreen]と書かれたキーがあると思います。
そのキーを押してみてください。
ノートPCの場合は左下付近にある[Fn]というキーがあると思いますがそのFnという文字と同じ色で
PrintScreenと書いてあるならば、[Fn]キーを押したまま[PrintScreen]のキーを押してください。

これでコピーが完了しました。

どこにコピーされたのでしょうか? → クリップボードです。
なので、ExcelやWordでもいいですし、アクセサリの中のペイントでもいいので
立ち上げて[Ctrl]+[V]で貼り付けてみてください。

あなたのPCの画面が画像として貼り付けられましたよね?

もし、ハードコピー用のユーティリティーなんかを常駐させている場合は直接プリンターへ
画面イメージが出力されたかもしれません。

さて、この場合はディスプレイに映っているものすべてがキャプチャされますが
特定のウィンドウだけをキャプチャしたい場合どうすればいいでしょうか。
まず、キャプチャしたいウィンドウを一番上にしてフォーカスを当てます(アクティブにします)
その状態で[Alt]キーを押したまま[PrintScreen]を押してください。
ノートの場合は[Fn]+[Alt]押したまま[PrintScreen]ですかね。
そしたらまたExcelでもWordでもペイントでもいいので貼り付けてみてください。

そのウィンドウだけがキャプチャされて貼り付けられましたよね?
こんな感じでw
amb001

さて、これが何の役に立つんでしょう?
PCで操作説明の資料を作る場合なんかはキャプチャ画像を使うとわかりやすいですね。
まぁ、PCで操作説明なんかの資料を作るような人は
画面コピーのやり方を知ってる人は多いと思いますが・・・

あと、エラーが発生した場合もその状態の画面を保存したりとか。

また、色んな設定した内容を記録するのにも設定内容を表示させてコピーすれば後で
設定しなおす場合なんかも便利です。

まぁ、それだけですけどねw

スマホなんかもスクリーンショットが保存できます。
iOSの場合は電源ボタンを押したままホームボタンを押すとシャッター音がして
スクリーンショットが保存されます。
Androidなんかはバージョンによって異なるようですが
4.0.xの場合は音量キーの↓と電源ボタンを同時に長押しで「カシャッ」と保存されます。
やりにくいですw

ただ、こういうキャプチャ画像はうっかり重要な情報を表示させたまま
ネットなんかに公開すると情報流出にもなりますので気をつけてください。

ネットや資料で使う場合は重要情報や変な情報が映りこんでないかをよく確認しないといけません。
もし、そういった情報が映りこんでいたらペイントや他の画像編集アプリなどでその部分を
塗りつぶしたりモザイクかけたりして隠しましょう
[ 1 ]      2件中 1-2件