| 
    
     |  | こんにちわ。お世話になっております。 
 54343の質問の方と似ているのですが、既に描画した絵をBitmapで保存する
 
 または、コピーがしたいのですが?どの様にすればいいのでしょうか?
 
 やりたい事は
 
 Worksheet1に置いたコマンドボタンをクリックすると、UserForm1とUserForm2
 
 がモードレスで表示される。(この時、UF1は画面の4/5,UF2は画面1/5の大きさで表示
 
 され、この二つのUserFormで全画面表示になる。)そしてUserForm2にある描画開始
 
 ボタンを押すと、UserForm1にAPIのLIneToなどを使って描画がされる。描画が終了
 
 したら、UserForm2にある終了ボタンを押すとUserForm1に書いた絵を保存ができる
 
 のならば保存を、できないのであればコピーをしてUserForm3(これもモードレスです
 
 )に表示してUF1,UF2をUnLoadしてUF3を表示したままworksheetに戻るという作業で
 
 す。
 
 
 再現できるようにコードをアップします。
 
 必要な物 新規ワークブックに
 
 Worksheet(1)にコマンドボタンを一つ(ボタンは右はしに)
 UserForm1
 UserForm2 にはコマンドボタン(オブジェクト名 描画開始、終了)の二つ
 (ボタンの配置は左側に縦に2つでおねがいします)
 UserForm3
 
 です。
 
 
 標準モジュールに
 
 Option Explicit
 
 'ウインドウのハンドル取得 API
 Public Declare Function FindWindow Lib "user32" _
 Alias "FindWindowA" (ByVal lpClassName As String, _
 ByVal lpWindowName As String) As Long
 
 'デバイスコンテキストのコピー用 API
 
 Public Declare Function BitBlt Lib "gdi32" _
 (ByVal hDesrDC As Long, ByVal X As Long, ByVal Y As Long, _
 ByVal nWidth As Long, ByVal nHeight As Long, ByVal _
 hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
 ByVal dwRop As Long) As Long
 
 Public Const SRCCOPY = &HCC0020 '定数 コピー元をコピー
 
 'デバイスコンテキスト取得 API
 Public Declare Function GetDC Lib "user32" _
 (ByVal hwnd As Long) As Long
 
 'デバイスコンテキストの開放 API
 Public Declare Function ReleaseDC Lib "user32" _
 (ByVal hwnd As Long, ByVal hdc As Long) As Long
 
 'ウインドウ情報取得 API
 Public Declare Function GetWindowRect Lib "user32" _
 (ByVal hwnd As Long, lpRect As RECT) As Long
 
 Public Type RECT
 Left As Long
 Top As Long
 Right As Long
 Buttom As Long
 End Type
 
 '描画時 開始位置指示 API
 Public Declare Function MoveToEx Lib "gdi32" _
 (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, _
 ByVal pLastPoint As Long) As Long
 
 '描画時 直線描画 API
 Public Declare Function LineTo Lib "gdi32" _
 (ByVal hdc As Long, ByVal XEnd As Long, _
 ByVal YEnd As Long) As Long
 
 
 Public UF1hwnd As Long 'UserForm1のハンドル
 Public UF1hDC As Long 'UserForm1のデバイスコンテキスト
 
 Public UF3hwnd As Long 'UserForm3のハンドル
 Public UF3hDC As Long 'UserForm3のデバイスコンテキスト
 
 
 Sub 描画()
 
 UserForm1.Show (vbModeless)
 UserForm2.Show (vbModeless)
 
 Call Form_size_change_and_move
 
 End Sub
 
 Sub Form_size_change_and_move()
 
 Dim HwndEXL As Long 'エクセルのハンドル
 Dim eRect As RECT  'RECT構造体
 
 Dim EXLtop As Long, EXLleft As Long, EXLright As Long, EXLbuttom As Long
 
 
 'エクセルのハンドル取得
 HwndEXL = FindWindow("XLMAIN", "Microsoft Excel - " & ThisWorkbook.Name)
 
 If HwndEXL = 0 Then GoTo err_trap:
 
 'エクセル画面の位置取得
 Call GetClientRect(HwndEXL, eRect)
 
 EXLleft = eRect.Left
 EXLtop = eRect.Top
 EXLright = eRect.Right
 EXLbuttom = eRect.Buttom
 
 'UserForm1 を画面の4/5の大きさに設定する
 
 With UserForm1
 .Left = EXLleft
 .Top = EXLtop
 .Width = ((EXLright - EXLleft) * (4 / 5)) * 72 / 96
 .Height = EXLbuttom * 72 / 96
 End With
 
 'UserForm2 を画面の1/5の大きさに設定する
 
 With UserForm2
 .Left = ((EXLright - EXLleft) * (4 / 5)) * 72 / 96
 .Top = EXLtop
 .Width = ((EXLright - EXLleft) * (1 / 5)) * 72 / 96
 .Height = EXLbuttom * 72 / 96
 End With
 
 Exit Sub
 
 err_trap:
 MsgBox "FindWindow エラー", vbCritical
 'これが出てしまう方はコンパネのフォルダ設定の
 '登録されてある拡張子は表示しないのチェックを外して下さい
 
 End Sub
 
 UserForm1のInitializeに
 
 Private Sub UserForm_Initialize()
 
 UserForm1.StartUpPosition = 0
 
 End Sub
 
 UserForm2のInitializeに
 
 Private Sub UserForm_Initialize()
 
 UserForm2.StartUpPosition = 0
 
 End Sub
 
 UserForm2 のコマンドボタンに
 
 Private Sub 終了_Click()
 Dim ret As Long  'BitBltが成功か否か?0=否 成功<>0
 
 'ここでしたい事は
 'UserForm1をUnLoadする前にUserForm3を表示し
 'UserForm1に描画した絵をUserForm3にコピーして
 'Worksheetに戻りたい(出来た絵を見ながら次の作業に
 '移りたい)
 
 '現状:BitBltを使うとフォーム同士が重なりあっていて
 'UserForm3が写りこんでしまう(UserForm1と3の大きさはどうしても
 'このくらいは必要)
 
 '本当はUserForm3の大きさにあわせて縮小したい
 'bitblt にはこだわってはいない
 'Bitmapで保存できるのならば、UserForm3にImageを配置し
 'LoadPictureで表示したい。(こちらの方が縮小など楽ですよね?)
 
 
 UserForm3.Show (vbModeless)
 
 'waitしないと描画に失敗することがある為
 
 Application.Wait (Now() + TimeValue("00:00:01"))
 
 ret = BitBlt(UF3hDC, 0, 0, UserForm1.Width, UserForm1.Height, _
 UF1hDC, 0, 0, SRCCOPY)
 
 
 Unload UserForm2
 Unload UserForm1
 End Sub
 
 
 Private Sub 描画開始_Click()
 
 '描画原点
 Dim centerX As Long, centerY As Long
 
 'UserForm1 のハンドル取得
 UF1hwnd = FindWindow(vbNullString, UserForm1.Caption)
 
 'UserForm1 のデバイスコンテキスト取得
 UF1hDC = GetDC(UF1hwnd)
 
 'UserForm1の中央の値の取得(正しい計算ではない)
 
 centerX = (UserForm1.Width * 96 / 72) / 2
 centerY = (UserForm1.Height * 96 / 72) / 2
 
 '描画原点に移動
 
 MoveToEx UF1hDC, centerX, centerY, 0
 
 '放射線上に円を書く
 
 With WorksheetFunction
 For i = 1 To 10000
 LineTo UF1hDC, centerX + (300 * Sin(.Radians(0.036 * i))), _
 centerY - (300 * Cos(.Radians(0.036 * i)))
 
 MoveToEx UF1hDC, centerX, centerY, 0
 Next
 
 End With
 
 End Sub
 
 
 UserForm3のInitializeに
 
 Private Sub UserForm_Initialize()
 
 UserForm3.StartUpPosition = 0
 
 End Sub
 
 worksheet1に
 
 Private Sub CommandButton1_Click()
 Call 描画
 End Sub
 
 で以上です。保存後worksheetのコマンドボタンを押して下さい。
 
 
 実際の作業ではUserForm2にリストボックスがありテキストファイルを読み込み
 
 listをスクロールさせながら対応する行を描画していきます。この作業が重く
 
 (例はXYの2次元描画ですが、XYZの3次元描画をしていきます。2万行ぐらいで
 
 描画終了まで、2、3分かかります。)UserForm1を消してしまうと同じ絵を見る
 
 のにまたまたなければいけない為質問させてもらいました。ヒント、またはURL
 
 でもよろしいのでよろしくお願いします。
 
 |  |