tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルクリップボードに自動保存
記事No3385
投稿日: 2006/03/22(Wed) 10:57
投稿者POD
[OSのVer]:WindowsXP SP2  [VBのVer]:VB 2005
はじめまして。現在VB 2005 EXPRESSの勉強中です。

教えていただきたいことは、チェックボックスをTRUEにした場合に自動的にディスクトップ画面

キャプチャーをクリップボードへ保存することが可能かどうかです。

これが可能であればいちいち
VBの実行画面 −> ディスクトップ表示 −> PrintScreen −> VBの実行画面とする必要
がなくなり手間が省けると思い質問いたしました。

宜しくお願いします。

[ツリー表示へ]
タイトルRe: クリップボードに自動保存
記事No3387
投稿日: 2006/03/22(Wed) 11:28
投稿者魔界の仮面弁士
細かい事ですが、ディスクトップ(disc-top)ではなく、デスクトップ(desktop)ですよね。

> 教えていただきたいことは、チェックボックスをTRUEにした場合に自動的にディスクトップ画面
> の
> キャプチャーをクリップボードへ保存することが可能かどうかです。

Dim ScreenSize As Size = Screen.PrimaryScreen.Bounds.Size
Using Bmp As New Bitmap(ScreenSize.Width, ScreenSize.Height)
  Using G As Graphics = Graphics.FromImage(Bmp)
    G.CopyFromScreen(0, 0, 0, 0, ScreenSize)
    Clipboard.SetImage(Bmp)
  End Using
End Using

[ツリー表示へ]
タイトルRe^2: クリップボードに自動保存
記事No3389
投稿日: 2006/03/22(Wed) 11:53
投稿者POD
[OSのVer]:Windows    [VBのVer]:VB.NET  
魔界の仮面弁士さん。早速のレスありがとうございます。

> 細かい事ですが、ディスクトップ(disc-top)ではなく、デスクトップ(desktop)ですよね。
ご指摘ありがとうございます。勘違いしておりました。

>Dim ScreenSize As Size = Screen.PrimaryScreen.Bounds.Size
>Using Bmp As New Bitmap(ScreenSize.Width, ScreenSize.Height)
>  Using G As Graphics = Graphics.FromImage(Bmp)
>    G.CopyFromScreen(0, 0, 0, 0, ScreenSize)
>    Clipboard.SetImage(Bmp)
>  End Using
>End Using
早速コピペし実行してみましたが、デスクトップ画面ではなく現在表示されている画面のハードコピー

クリップボードに保存されてしまいました。Usingの使用方法が分かっていませんので勉強しますが、な
んとかチェックボックスをクリックした時に自動でデスクトップ画面をキャプチャーできないでしょう
か?

[ツリー表示へ]
タイトルRe: クリップボードに自動保存
記事No3388
投稿日: 2006/03/22(Wed) 11:39
投稿者YAS
あぅ,書いている間に魔界の仮面弁士さんが同じことをお書きになられました...

魔界の仮面弁士さんと同じ内容なので必要ないのですが,ちょっと前に自分でもまとめましたので参考
にしてください。

hhttp://homepage1.nifty.com/yasunari/VB/VB2005/ScreenCapture.htm

[ツリー表示へ]
タイトルRe^2: クリップボードに自動保存
記事No3390
投稿日: 2006/03/22(Wed) 12:12
投稿者POD
YASさん。レスありがとうございます。
> hhttp://homepage1.nifty.com/yasunari/VB/VB2005/ScreenCapture.htm
見させていただきました。
ここで書かれていますプライマリスクリーンとは現在ディスプレー上に表示されているもののことをさ

ているのでしょうか?やはりディスプレイ上に表示されていないデスクトップ画面のハードコピーはで

ないのでしょうか?
できないのであれば以下のようにはできませんか?
   1.VBフォームからチェックボックスにチェック
   2.画面をデスクトップ画面に切替
   3.PRINTSCREEN
   4.VBフォーム表示
な具合です。

[ツリー表示へ]
タイトルRe^3: クリップボードに自動保存
記事No3391
投稿日: 2006/03/22(Wed) 12:22
投稿者YAS
> ているのでしょうか?やはりディスプレイ上に表示されていないデスクトップ画面のハードコピーは

申し訳ありませんが,「ディスプレイ上に表示されていないデスクトップ画面」の意味がわかりませ
ん。
「デスクトップ画面」というもののPODさんにとっての定義を詳しく説明して頂けますか?

[ツリー表示へ]
タイトルRe^4: クリップボードに自動保存
記事No3393
投稿日: 2006/03/22(Wed) 12:30
投稿者POD
分かりにくくて申し訳ありません。
デスクトップ画面=PC起動後の初期画面
ディスプレイ上の画面=現在、ディスプレイ上に表示されている状態(例えばOUTLOOKが全画面で表示さ
れている)。
です。

[ツリー表示へ]
タイトルRe^5: クリップボードに自動保存
記事No3395
投稿日: 2006/03/22(Wed) 13:00
投稿者YAS
それならフォームを最小化して,タスクバーからも消して,それからキャプチャすればよいでしょう。
自分自身以外のアプリケーションをタスクバーから消すのは難儀なので,自分で閉じてください。

Option Strict On
Public Class Form1

    Private Sub Form1_KeyDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.Control = True And e.KeyCode = Keys.C Then
            Dim WndState As FormWindowState = Me.WindowState
            Me.WindowState = FormWindowState.Minimized
            Me.ShowInTaskbar = False
            Using Image As Image = New Bitmap(Screen.PrimaryScreen.Bounds.Width, _
                                              Screen.PrimaryScreen.Bounds.Height)
                Using Graph As Graphics = Graphics.FromImage(Image)
                    Graph.CopyFromScreen(New Point(0, 0), New Point(0, 0), _
                                         Screen.PrimaryScreen.Bounds.Size)
                End Using
                Clipboard.SetImage(Image)
                Me.WindowState = WndState
                Me.ShowInTaskbar = True
                Me.BackgroundImage = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
                Using Graph As Graphics = Graphics.FromImage(Me.BackgroundImage)
                    Graph.InterpolationMode = _
                        Drawing2D.InterpolationMode.HighQualityBicubic
                    Graph.DrawImage(Image, New Rectangle(New Point(0, 0), _
                                    Me.BackgroundImage.Size))
                End Using
            End Using
        End If
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) Handles MyBase.Load
        Me.KeyPreview = True
    End Sub

End Class

[ツリー表示へ]
タイトルRe^6: クリップボードに自動保存
記事No3397
投稿日: 2006/03/22(Wed) 15:42
投稿者POD
後は自分自身以外のアプリケーションタスクを最小化するだけですね。
がんばってやってみます。

ありがとうございました。

[ツリー表示へ]
タイトルRe^7: クリップボードに自動保存
記事No3399
投稿日: 2006/03/22(Wed) 16:33
投稿者YAS
> 後は自分自身以外のアプリケーションタスクを最小化するだけですね。
> がんばってやってみます。

私が「自分自身以外のアプリケーションをタスクバーから消すのは難儀なので,自分で閉じてくださ
い。」と書いたのは「自分で考えろ」という意味ではなくて,手動でマウスなりキーボードなりを操作
して最小化した方が速いのでは?と言う意味ですよ。

もちろん,挑戦なさると言うのを止めはしませんが,プログラムにするのはかなり面倒だと思います。

[ツリー表示へ]
タイトルRe^8: クリップボードに自動保存
記事No3404
投稿日: 2006/03/22(Wed) 22:07
投稿者POD
YASさんいろいろ調べてみた結果、CreateObject("Shell.Application").ToggleDesktop()とい
う1文でデ
スクトップ画面の表示ができるようです。但し、完全にデスクトップが表示される前にコピーがとられ

ようで毎回タイミングによりクリップボードにコピーされる画像が違ってしまいます。CreateObject
("Shell.Application").ToggleDesktop()の後にウェイトをかませる。もしくは完全にデスク
トップが表
示されるまで後の処理を行わないようにできればいいのですが......
なにぶんあまり経験がありませんのでこのようにしたらプログラミングがもっとすっきりする等のアド

イスがあればお願いします。


    Private Sub CheckBox5_MouseClick(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles CheckBox5.MouseClick

        If CheckBox5.Checked = True Then

            Dim WndState As FormWindowState = Me.WindowState
            Me.WindowState = FormWindowState.Minimized
            Me.ShowInTaskbar = False

            CreateObject("Shell.Application").ToggleDesktop()

            Dim ScreenSize As Size = Screen.PrimaryScreen.Bounds.Size
            Using Bmp As New Bitmap(ScreenSize.Width, ScreenSize.Height)
                Using G As Graphics = Graphics.FromImage(Bmp)
                    G.CopyFromScreen(0, 0, 0, 0, ScreenSize)
                    Clipboard.SetImage(Bmp)
                End Using
            End Using

            Dim iData As IDataObject = Clipboard.GetDataObject()
            'クリップボードにBMPファイルがあれば
            'WorkCopyPath="C:\WINDOWS\TEMP\DiskTop.jpeg"に保存
            If iData.GetDataPresent(DataFormats.Bitmap) Then
                Dim img As System.Drawing.Image = iData.GetData(DataFormats.Bitmap, True)
                'Jpeg 形式で保存
                img.Save(WorkCopyPath, System.Drawing.Imaging.ImageFormat.Jpeg)
            End If

            Me.WindowState = WndState
            Me.ShowInTaskbar = True

        End If

    End Sub

[ツリー表示へ]
タイトルRe^9: クリップボードに自動保存
記事No3408
投稿日: 2006/03/22(Wed) 23:53
投稿者YAS
ツリーが長くなってきたので見やすくなるよう,初めの投稿に返信しました。

[ツリー表示へ]
タイトルRe^3: クリップボードに自動保存
記事No3392
投稿日: 2006/03/22(Wed) 12:29
投稿者YAS
> ここで書かれていますプライマリスクリーンとは現在ディスプレー上に表示されているもののことを

プライマリディスプレイというのは,例えばデュアルディスプレイ(2台のディスプレイを同時に使
う)のときに,「主」になる方のディスプレイのことです。Print-Screenキーだとプライマリディス
プレイとセカンダリディスプレイが合体した画像がクリップボードにコピーされます。

>2.画面をデスクトップ画面に切替

フォームを最小化するという意味でしょうか?

[ツリー表示へ]
タイトルRe^4: クリップボードに自動保存
記事No3394
投稿日: 2006/03/22(Wed) 12:56
投稿者POD
> > ここで書かれていますプライマリスクリーンとは現在ディスプレー上に表示されているものの
ことを
>
> プライマリディスプレイというのは,例えばデュアルディスプレイ(2台のディスプレイを同時に
使
> う)のときに,「主」になる方のディスプレイのことです。Print-Screenキーだとプライマリディ

> プレイとセカンダリディスプレイが合体した画像がクリップボードにコピーされます。
シングルディスプレイです。

>
> >2.画面をデスクトップ画面に切替
>
> フォームを最小化するという意味でしょうか?
クイックランチャーの”デスクトップの表示”ボタンを押した状態にすることです。

うまく説明できなくて申し訳ありませんが宜しくお願いします。

[ツリー表示へ]
タイトルRe: クリップボードに自動保存
記事No3407
投稿日: 2006/03/22(Wed) 23:47
投稿者YAS
ツリーが長くなってきたので,見やすくなるよう,最初の投稿に返信をします。

>CreateObject("Shell.Application").ToggleDesktop()

おぉ!すばらしい。いいやり方を見つけになりましたね。私は知りませんでした。
ただ,CreateObjectということはこれはCOMオブジェクトだと思いますし,Option Strict On
にすると遅延バインディングが禁止になりますので,次のようにするとよいと思います。

            Dim Obj As Object = Nothing
            Try
                Obj = CreateObject("Shell.Application")
                Obj.GetType.InvokeMember("ToggleDesktop", _
                    Reflection.BindingFlags.InvokeMethod, Nothing, Obj, Nothing)
            Catch ex As Exception
                If Obj IsNot Nothing Then Marshal.ReleaseComObject(Obj)
            End Try

これでCOMオブジェクトが解放され,かつOption Strict Onでもエラーになりません。

あとは,ウィンドウが全部最小化されたことを判断すればよいのでしょうが,申し訳ありませんが,
私にはわかりません。
下のような非常に長めのウエイトをかませる位しか思いつきません。

System.Threading.Thread.Sleep(3000)

>Dim iData As IDataObject = Clipboard.GetDataObject()
>'クリップボードにBMPファイルがあれば
>'WorkCopyPath="C:\WINDOWS\TEMP\DiskTop.jpeg"に保存
>If iData.GetDataPresent(DataFormats.Bitmap) Then
>Dim img As System.Drawing.Image = iData.GetData(DataFormats.Bitmap, True)
>'Jpeg 形式で保存
>img.Save(WorkCopyPath, System.Drawing.Imaging.ImageFormat.Jpeg)

ここの部分の意味がよくわかりませんが,ファイルに保存するだけならクリップボードに
コピーなどせず,キャプチャした直後にImageオブジェクトから直接保存したらよいのでは?

[ツリー表示へ]
タイトルRe^2: クリップボードに自動保存
記事No3409
投稿日: 2006/03/23(Thu) 01:53
投稿者魔界の仮面弁士
> ただ,CreateObjectということはこれはCOMオブジェクトだと思いますし,Option Strict On
> にすると遅延バインディングが禁止になりますので,次のようにするとよいと思います。

Type 経由でも良いですが、VB.NET の場合は、CallByName を使った方が楽かも。

[ツリー表示へ]
タイトルRe^3: クリップボードに自動保存
記事No3410
投稿日: 2006/03/23(Thu) 02:51
投稿者YAS
魔界の仮面弁士さん,ご助言ありがとうございます。

> Type 経由でも良いですが、VB.NET の場合は、CallByName を使った方が楽かも。

前に,遅延バインディング,Type.InvokeMemberメソッド,CallByName関数の3つの処理スピードを
簡単に計測したところ,微妙な差でしたが,

1 Type.InvokeMemberメソッド
2 遅延バインディング
3 CallByName関数

の順でしたので,Type.InvokeMemberメソッドを好んで使っておりました。
しかし,確かにCallByName関数の方が手軽ですね。

[ツリー表示へ]
タイトルRe^4: クリップボードに自動保存
記事No3411
投稿日: 2006/03/23(Thu) 09:35
投稿者POD
YASさん、魔界の仮面弁士さんありがとうございます。
現在はFOR〜NEXTを使用しウェイトを設定しておりますが、CallByName関数について調べて使用

てみたいと思います。いろいろとありがとうございました。又、何か分からないことがありましたら宜

くお願いします。

[ツリー表示へ]
タイトルRe^5: クリップボードに自動保存
記事No3412
投稿日: 2006/03/23(Thu) 09:46
投稿者YAS
> 現在はFOR〜NEXTを使用しウェイトを設定しておりますが、CallByName関数について調べて
使

ループの中身にもよりますが,For-Nextでは処理能力の違う機械で実行したときに待ち時間が変わって
しまって期待した動作にならなくなりませんか?

[ツリー表示へ]
タイトルRe^6: クリップボードに自動保存
記事No3413
投稿日: 2006/03/23(Thu) 09:59
投稿者POD
たびたびありがとうございます。
> ループの中身にもよりますが,For-Nextでは処理能力の違う機械で実行したときに待ち時間が変わ
って
> しまって期待した動作にならなくなりませんか?
確かにそのとうりでした。

今、Visual Studio 2005のHELPでCallByName 関数を見ているのですがいまいち分かりません。
相変わらずマイクロソフトのHELPは初心者には分かりにくいようで.....

[ツリー表示へ]
タイトルRe^7: クリップボードに自動保存
記事No3414
投稿日: 2006/03/23(Thu) 10:43
投稿者YAS
> 今、Visual Studio 2005のHELPでCallByName 関数を見ているのですがいまいち分かりません。
> 相変わらずマイクロソフトのHELPは初心者には分かりにくいようで.....

Dim Obj As Object = CreateObject("Shell.Application")

とあったときに,

遅延バインディング:Obj.ToggleDesktop()

CallByName関数:CallByName(Obj, "ToggleDesktop", CallType.Method, Nothing)

Type.InvokeMemberメソッド:Obj.GetType.InvokeMember("ToggleDesktop", _
                           Reflection.BindingFlags.InvokeMethod, Nothing, Obj, Nothing)

の3つが結果だけをみればほぼ等価に機能します。

もちろん,ObjはCOMオブジェクトなので使い終わったら解放する必要があります。
        
        Dim Obj As Object = Nothing
        Try
            Obj = CreateObject("Shell.Application")
            CallByName(Obj, "ToggleDesktop", CallType.Method, Nothing)
        Catch ex As Exception
            If Obj IsNot Nothing Then Marshal.ReleaseComObject(Obj)
        End Try

[ツリー表示へ]
タイトルRe^8: クリップボードに自動保存
記事No3416
投稿日: 2006/03/23(Thu) 11:37
投稿者POD
3種類全て試してみましたが、完全にデスクトップ画面が表示される前にハードコピーがされてしまいま
す。私のPCの処理能力が遅い為、複数のアプリケーションが立ち上がっている状態で実行すると処理

追いつかないようですので”System.Threading.Thread.Sleep(3000)”で対応したいと思います。

[ツリー表示へ]
タイトルRe^9: クリップボードに自動保存
記事No3417
投稿日: 2006/03/23(Thu) 12:20
投稿者YAS
[OSのVer]:Windows    [VBのVer]:VB.NET  
> 3種類全て試してみましたが、完全にデスクトップ画面が表示される前にハードコピーがされてしま
いま
> す。私のPCの処理能力が遅い為、複数のアプリケーションが立ち上がっている状態で実行すると処

> が
> 追いつかないようですので”System.Threading.Thread.Sleep(3000)”で対応したいと思います。


CallByNameは同期をとる関数ではなくて,単にメソッドを名前で指定して実行する関数ですよ。
「Option Strict Onで動作するようなコードにするにはどうしたらよいか」ということを説明したの
です。

デスクトップのウィンドウが全部最小化したかどうか調べるには,見えているウィンドウを列挙して
そのウィンドウの状態を調べる必要があります。(デスクトップそのものやIMEを除いて)
しかも,最小化中なのか最小化が完了したのかなどの判別も必要なので,やはり簡単にはできないと
思います。

[ツリー表示へ]
タイトルRe^10: クリップボードに自動保存
記事No3418
投稿日: 2006/03/23(Thu) 12:31
投稿者POD
>CallByNameは同期をとる関数ではなくて,単にメソッドを名前で指定して実行する関数ですよ。
>「Option Strict Onで動作するようなコードにするにはどうしたらよいか」ということを説明した

>です。
そのようですね。

>デスクトップのウィンドウが全部最小化したかどうか調べるには,見えているウィンドウを列挙し

>そのウィンドウの状態を調べる必要があります。(デスクトップそのものやIMEを除いて)
>しかも,最小化中なのか最小化が完了したのかなどの判別も必要なので,やはり簡単にはできない

>思います。
やはりむずかしそうですね。十分、ウェイト時間をとって対応します。

重ね重ねありがとうございました。

[ツリー表示へ]