開発言語:VB6
お世話になります。
DEVMODE構造体とDEVNAME構造体に、プリンタや用紙サイズ、印刷の向きなどを指定し、Win32APIのPrintDialogで印刷ダイアログを表示しています。
この処理を何回か呼び出すと、プログラムが異常終了します。
異常終了する場所は、PrintDialogを呼び出した直後だと思われます。
いろいろ調べたのですが、原因がわかりません。
長くなりますが、ソースコードの一部を添付させて頂きます。
ご覧頂き、おかしい点などございましたらご指摘いただけるとありがたいです。
よろしくお願いします。
以下ソースコード
-----------------------------------------------------------------------------------
PrintDlg.lStructSize = Len(PrintDlg)
PrintDlg.hwndOwner = phwnd
PrintDlg.flags = plngPrintFlags
strDeviceName = Printer.DeviceName
strDriverName = Printer.DriverName
sngPaperBin = Printer.PaperBin
strPortNo = Printer.Port
If mstrDriverName <> "" And _
mstrDeviceName <> "" And _
mstrPortNo <> "" Or _
msngDefaultSource <> 0 Then
For Each objPrinter In Printers
If objPrinter.DeviceName = mstrDeviceName Then
strDeviceName = mstrDeviceName
strDriverName = mstrDriverName
sngPaperBin = msngDefaultSource
strPortNo = mstrPortNo
Exit For
End If
Next
End If
udtPrinterDefaults.DesiredAccess = PRINTER_ACCESS_USE
If OpenPrinter(Trim(strDeviceName), hPrinter, udtPrinterDefaults) <> 0 Then
bufSize = DocumentProperties(NULLPTR, hPrinter, Trim(strDeviceName), NULLPTR, NULLPTR, 0)
If bufSize < 1 Then
MsgBox "プリンタ情報の取得に失敗しました。", vbCritical
GoTo Exit_Proc
Else
ReDim aDevMode(bufSize - 1)
Call DocumentProperties(NULLPTR, hPrinter, Trim(strDeviceName), aDevMode(0), NULLPTR, DM_OUT_BUFFER)
Call CopyMemory(DevMode, aDevMode(0), Len(DevMode))
End If
Call ClosePrinter(hPrinter)
Else
MsgBox Err.LastDllError
MsgBox "プリンタの取得に失敗しました。", vbCritical
GoTo Exit_Proc
End If
DevMode.dmPaperSize = mintPaperSize
DevMode.dmOrientation = mintPaperOrnt
DevMode.dmDefaultSource = sngPaperBin
PrintDlg.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, Len(DevMode))
lpDevMode = GlobalLock(PrintDlg.hDevMode)
If lpDevMode > 0 Then
CopyMemory ByVal lpDevMode, DevMode, Len(DevMode)
bReturn = GlobalUnlock(lpDevMode)
End If
With DevName
.wDriverOffset = 8
.wDeviceOffset = .wDriverOffset + 1 + Len(strDriverName)
.wOutputOffset = .wDeviceOffset + 1 + Len(strDeviceName)
.wDefault = 0
.extra = strDriverName & Chr(0) & strDeviceName & Chr(0) & strPortNo & Chr(0)
End With
PrintDlg.hDevNames = GlobalAlloc(GMEM_MOVEABLE Or _
GMEM_ZEROINIT, Len(DevName))
lpDevName = GlobalLock(PrintDlg.hDevNames)
If lpDevName > 0 Then
CopyMemory ByVal lpDevName, DevName, Len(DevName)
bReturn = GlobalUnlock(lpDevName)
End If
If PrintDialog(PrintDlg) Then
mhDC = PrintDlg.hdc
lpDevName = GlobalLock(PrintDlg.hDevNames)
CopyMemory DevName, ByVal lpDevName, Len(DevName)
bReturn = GlobalUnlock(lpDevName)
GlobalFree PrintDlg.hDevNames
lpDevMode = GlobalLock(PrintDlg.hDevMode)
CopyMemory DevMode, ByVal lpDevMode, Len(DevMode)
bReturn = GlobalUnlock(PrintDlg.hDevMode)
GlobalFree PrintDlg.hDevMode
mstrDriverName = Mid(DevName.extra, DevName.wDriverOffset - 8 + 1)
mstrDriverName = Left(mstrDriverName, InStr(mstrDriverName, Chr(0)) - 1)
mstrDeviceName = Mid(DevName.extra, DevName.wDeviceOffset - 8 + 1)
mstrDeviceName = Left(mstrDeviceName, InStr(mstrDeviceName, Chr(0)) - 1)
mstrPortNo = Mid(DevName.extra, DevName.wOutputOffset - 8 + 1)
mstrPortNo = Left(mstrPortNo, InStr(mstrPortNo, Chr(0)) - 1)
msngDefaultSource = DevMode.dmDefaultSource
mintPaperOrnt = DevMode.dmOrientation
mintPaperSize = DevMode.dmPaperSize
gfShowPrinter = True
End If
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
#2 です。
なかなか解決できずに困っていらっしゃるようですね・・・・・・。前者の方法も後者と効果は変わらないようにおもいますが、以下のような感じですね。
(DevMode の設定値変更後のコメントが付いている 3 行が追加変更です)
-----
DevMode.dmPaperSize = mintPaperSize
DevMode.dmOrientation = mintPaperOrnt
DevMode.dmDefaultSource = sngPaperBin
CopyMemory aDevMode(0), DevMode, Len(DevMode) ' 追加、DevMode を aDevMode に書き戻す
PrintDlg.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, bufSize) ' バッファサイズを bufSize に
lpDevMode = GlobalLock(PrintDlg.hDevMode)
If lpDevMode > 0 Then
CopyMemory ByVal lpDevMode, aDevMode(0), bufSize 'コピー元を aDevMode に、サイズを bufSize に
bReturn = GlobalUnlock(lpDevMode)
-----
aDevMode のサイズが DevMode と同じであれば意味はありません。ダイアログ表示後に取り出すデータは必要なとこだけ取り出せればいいので、DevMode に取り出すことで問題ないと思います。
解決できるといいですね・・・・・・・。
No.2
- 回答日時:
DEVMODE の扱いがちょっと気になりました。
一応調べてみたほうがいいかも・・・・・・レベルなのですが、書きます。DEVMODE というのはデバイスによってサイズが違うことになっているため、単一の DEVMODE 構造体で全体を表現することはできないことになっています。
DevMode 変数の構造がわからないのですが、おそらくどのデバイスでも共通部分の構造体のみが定義されているのではないかと推測しますが、デバイスが返す DEVMODE は、そのデバイス固有の Private エリアがあり、そのためサイズが一定しないことになっています(ソースで使われている DevMode という変数のサイズと、サイズを取得して ReDim した aDevMode のサイズが違うことがあると考えます)。
このため、aDevMode から DevMode だけ引き出し、内容を設定して hDevMode に DevMode のサイズ分だけ設定しているため、プライベートエリアの情報が欠落(というか範囲外のメモリなので不定値になってしまっている)と考えられます。
対処法は2つ考えられます。ひとつは DevMode を設定した後、DevMode をもう一度 aDevMode に書き戻し、hDevMode には aDevMode 分のサイズのメモリを確保・設定します。
もう一つはDevMode 構造体の最後に、必要以上の空の配列でも用意していおいて(要は余裕で aDevMode が入るであろうサイズ)、aDevMode をそっくり DevMode にコピーしてから DevMode を設定し、hDevMode に DevMode のサイズを確保・設定します(aDevMode 分のサイズでもいいはずですが、大きい分には構わないはず)。
という感じでは・・・・・・・、とちょっと推測します。おそらく、範囲外になっているプライベートエリアの部分が、最初は 0 フィルされていたのが実行中にダーティデータ化して誤動作しているのでは、と推測しています。
ちょっと長くてごめんなさい。一度確認してみてはいかがでしょうか??
この回答への補足
引き続きご回答を頂けるとありがたいです。
>対処法は2つ考えられます。ひとつは DevMode を設定した後、DevMode をもう一度 aDevMode に書き戻し
>hDevMode には aDevMode 分のサイズのメモリを確保・設定します。
ひとつめの方法、具体的にどのようなコーディングになりますでしょうか?
お手数をおかけして申し訳ありませんが、ご教示いただけるとありがたいです。
よろしくお願いします。
回答を頂きありがとうございました。(お礼が遅くなり申し訳ありません)
> もう一つはDevMode 構造体の最後に、必要以上の空の配列でも用意していおいて(要は余裕で
> aDevMode が入るであろうサイズ)、aDevMode をそっくり DevMode にコピーしてから DevMode
> を設定し、hDevMode に DevMode のサイズを確保・設定します(aDevMode 分のサイズでもいいは
> ずですが、大きい分には構わないはず)。
こちらを試してみました。
具体的には、DevMode 構造体の最後に、以下の1行を追加しました。
dmFiller(2048) As Byte
が、うまくいきませんでした。
その後、いろいろ試しているのですが、未だ解決には至っておりません。
もし、また何かありましたらお願いします。
No.1
- 回答日時:
>PrintDlg.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, Len(DevMode))
>lpDevMode = GlobalLock(PrintDlg.hDevMode)
これらのハンドルは解放されていますか。
思いつくのはこれぐらいですが。
回答を頂きありがとうございました。(お礼が遅くなり申し訳ありません)
最後に、以下の2行を追加してみましたが、ダメでした。
GlobalFree PrintDlg.hDevNames
GlobalFree PrintDlg.hDevMode
その後、いろいろ試しているのですが、未だ解決には至っておりません。
もし、また何かありましたらお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Visual Basic(VBA) ExcelのVBAコードについて教えてください。 1 2023/02/02 09:25
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- Excel(エクセル) エクセルVBAでオブジェクトが必要です 2 2022/09/10 16:37
- Visual Basic(VBA) VBAの繰り返し処理について教えてください。 3 2022/08/02 13:21
- Excel(エクセル) VBAについて 3 2022/06/19 18:19
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- Visual Basic(VBA) VBA 請求書自動作成 3 2022/04/24 01:58
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) 【追加】ファイルを閉じてダイアログで保存した時だけ処理の実行をする 3 2022/03/23 15:43
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ちんこの通常の長さについて
-
中一で勃起時6センチぐらいって...
-
ペニスサイズについて質問です...
-
メールサイズ超過とGmailで送れ...
-
ボタン電池のL1131と1130 はサ...
-
ディスク上のサイズとサイズは...
-
みかん箱サイズって具体的にど...
-
B4サイズは何インチ?
-
中3です、ちんこのサイズがMAX...
-
アプリケーションのタイトルバ...
-
TOSHIBA REGZA 32インチの次の...
-
春巻きの皮 ミニサイズの大き...
-
アパレルで 10pcs の意味を教...
-
ユニクロのジーンズ、メンズと...
-
iPhone Pro MAX→iPhoneProに買...
-
LINEで動画を送信しようとする...
-
オブジェクトのサイズが勝手に...
-
子ども用のパンツで大人が履け...
-
たばこの箱のサイズ
-
紳士服のLサイズは、婦人服で言...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ちんこの通常の長さについて
-
中一で勃起時6センチぐらいって...
-
ペニスサイズについて質問です...
-
中3です、ちんこのサイズがMAX...
-
15.6インチのノートパソコンの...
-
オブジェクトのサイズが勝手に...
-
みかん箱サイズって具体的にど...
-
春巻きの皮 ミニサイズの大き...
-
B4サイズは何インチ?
-
255cmより小さエンジン式の草...
-
医療用画像記録フィルムのサイ...
-
ユニクロのLサイズは、無印良品...
-
偽サイズSSD の見分け方につい...
-
コンビニコーヒーカップの犯罪...
-
エクスプローラとプロパティで...
-
ディスク上のサイズとサイズは...
-
ms access 2013で、チェックボ...
-
スマートフォンの AQUOS SH-01L...
-
これは団地間?江戸間??????
-
Access チェックボックスやオプ...
おすすめ情報