- 水穂和明
- 会議室デビュー日: 2001/12/25
- 投稿数: 6
- お住まい・勤務地: 鳥取県米子市
|
投稿日時: 2007-12-28 11:55
VB2005を使ってプリンタダイアログを自前で作っています。
そこでプリンタ詳細ダイアログで設定した情報をファイルにセーブ/ロードしたいです。
下記の方法を試したところ機種依存部分もセーブしたかったのですができないようです。
また別の方法として、GetHdevmode()でDEVMODE構造体に保存してみたりしたのですがうまく動作しません。
どなたか、機種依存部分も保持した形でセーブ/ロードする方法をご存じの方がいらっしゃいませんでしょうか?
アドバイスを頂けると幸いです。
とりあえず、機種依存部分以外を保存/読み込みできるロジック。
コード: |
|
'PrinterSettingsをファイルに保存。
Public Shared Sub SaveToBinaryFile( _
ByVal obj As PrinterSettings, ByVal path As String)
Dim fs As FileStream
Dim bf As BinaryFormatter
fs = New FileStream(path, FileMode.Create, FileAccess.Write)
bf = New BinaryFormatter()
'シリアル化して書き込む
bf.Serialize(fs, obj)
fs.Close()
End Sub
'PrinterSettingsをファイルより読み込み。
Public Shared Function LoadFromBinaryFile(ByVal path As String) _
As PrinterSettings
Dim dsp As PrinterSettings '= New PrinterSettings
Dim fs As FileStream
Dim bf As BinaryFormatter
fs = New FileStream(path, FileMode.Open, FileAccess.Read)
bf = New BinaryFormatter()
'読み込んで逆シリアル化する
dsp = CType(bf.Deserialize(fs), PrinterSettings)
fs.Close()
Return dsp
End Function
|
参考までにプリンタ詳細設定ダイアログを表示、値を保持するロジック。
コード: |
|
Public Function GetDevMode(ByVal Device As String) As Integer
Dim ret As Integer
Dim hPrinter As IntPtr
Dim PtrDMOut As IntPtr
Dim PtrDMIn As IntPtr
Dim _PrinterName As String = Device
PtrDMIn = _PS.GetHdevmode(_PS.DefaultPageSettings)
PtrDMOut = _PS.GetHdevmode(_PS.DefaultPageSettings)
Dim globalDevIn As IntPtr = GlobalLock(PtrDMIn)
Dim globalDevOut As IntPtr = GlobalLock(PtrDMOut)
Try
'プリンタのハンドルを取得
ret = OpenPrinter(_PrinterName, hPrinter, IntPtr.Zero)
If ret = 0 Or hPrinter.Equals(IntPtr.Zero) Then
Return 0
End If
'DialogBox 表示
ret = DocumentProperties(Me.Handle, hPrinter, _PrinterName, _
globalDevOut, globalDevIn, _
DM_IN_PROMPT Or DM_IN_BUFFER Or DM_OUT_BUFFER)
If PtrDMOut.Equals(IntPtr.Zero) Then
Return 0
End If
'DialogBoxでOKがクリックされた場合に設定内容を反映させる。
If ret = 1 Then
_PS.DefaultPageSettings.SetHdevmode(globalDevOut)
_PS.SetHdevmode(globalDevOut)
Me.Setvalues()
End If
Return ret
Catch ex As Exception
'エラー処理
Finally
GlobalUnlock(PtrDMIn)
GlobalFree(PtrDMIn)
GlobalUnlock(PtrDMOut)
GlobalFree(PtrDMOut)
If Not hPrinter.Equals(IntPtr.Zero) Then
ClosePrinter(hPrinter)
End If
End Try
End Function
|
よろしくお願いします。
//リゾナンス 水穂和明
|
- Jitta
- ぬし
- 会議室デビュー日: 2002/07/05
- 投稿数: 6267
- お住まい・勤務地: 兵庫県・海手
|
投稿日時: 2008-01-03 21:18
おそらく、ドライバに直接尋ねることになると思います。
DDK のリファレンスをあたってみてください。ドライバが必ず実装しなければならない関数があると思います。その関数を呼び出すとかして、とれたものを保存するとかになるかと思います。
最後には、メーカーに聞かないと情報は出てこないと思います。
|
- 未記入
- ぬし
- 会議室デビュー日: 2004/09/17
- 投稿数: 667
|
投稿日時: 2008-01-04 21:37
ドライバに直接尋ねる必要はないでしょう。
DEVMODE のプライベート領域が保存できていないのは、BinaryFormater に PrinterSettings インスタンスを与えてバイト配列化しているからだと思います。(この時点でパブリック領域しか保存されないはず。)
プライベート領域を保存・復元する場合は、PrinterSettings インスタンスではなく、DEVMODE 構造体を直接保存したらよいと思います。DEVMODE 構造体は末尾にプライベート領域があるためサイズが固定ではありません。DocumentProperties 関数の最後の引数に 0 を指定することで、プライベート領域も含めた必要サイズが分かります。また、DEVMODE 構造体の dmDriverExtra にもプライベート領域のサイズが入っています。
.NET のことは知らないのですが、PrinterSettings というクラスは、おそらく、パブリック領域を扱うためのクラスなのでしょう。(当たり前ですが、プライベート領域はプリンタ依存ですので標準クラスライブラリでクラス化するようなことはできません。) たぶん、PrinterSettings インスタンスはプライベート領域を保持しないのでありませんか?
|
- Azulean
- 大ベテラン
- 会議室デビュー日: 2008/01/04
- 投稿数: 123
- お住まい・勤務地: 大阪府
|
投稿日時: 2008-01-04 22:32
引用: |
|
未記入さんの書き込み (2008-01-04 21:37) より:
.NET のことは知らないのですが、PrinterSettings というクラスは、おそらく、パブリック領域を扱うためのクラスなのでしょう。(当たり前ですが、プライベート領域はプリンタ依存ですので標準クラスライブラリでクラス化するようなことはできません。) たぶん、PrinterSettings インスタンスはプライベート領域を保持しないのでありませんか?
|
プライベート領域の面倒までは見てくれないように見受けられます。
GetHdevmodeメソッドがあるので、バイト数を調べて、自分でシリアライズする必要があるのだと思います(未確認)。
http://msdn2.microsoft.com/ja-jp/library/system.drawing.printing.printersettings.gethdevmode(VS.80).aspx
http://msdn2.microsoft.com/ja-jp/library/system.drawing.printing.printersettings.sethdevmode(VS.80).aspx
|
- 水穂和明
- 会議室デビュー日: 2001/12/25
- 投稿数: 6
- お住まい・勤務地: 鳥取県米子市
|
投稿日時: 2008-01-06 16:50
引用: |
| DEVMODE 構造体は末尾にプライベート領域があるためサイズが固定ではありません。DocumentProperties 関数の最後の引数に 0 を指定することで、プライベート領域も含めた必要サイズが分かります。また、DEVMODE 構造体の dmDriverExtra にもプライベート領域のサイズが入っています。
|
ここらへんの知識がありませんでした。
ありがとうございます。
あとDEVMODEはGetHDevmode()とSetHDevmode()を使おうと考えております。
いま、テストできる環境がないので明日試してみたいと思います。
何か進展がありましたら報告させていただきます。
|
- 水穂和明
- 会議室デビュー日: 2001/12/25
- 投稿数: 6
- お住まい・勤務地: 鳥取県米子市
|
投稿日時: 2008-01-07 15:18
今までのやりとりを踏まえて、保存/読み込みできるはずのロジックを組んでみたのですが、SetHdevmode()したあとメモリを破壊しているようでうまく先に進みません。
あと一歩かと思うのですがアドバイスいただけませんでしょうか?
コード: |
|
Public Shared Sub SaveToBinaryFile( _
ByVal obj As PrinterSettings, ByVal path As String)
Dim PtrDevMode As IntPtr
Dim testDevmode As New DEVMODE
Dim bytReadBuf(2036) As Byte
PtrDevMode = obj.GetHdevmode(obj.DefaultPageSettings)
Dim globalDevOut As IntPtr = GlobalLock(PtrDevMode)
testDevmode = CType(Marshal.PtrToStructure(globalDevOut, _
GetType(DEVMODE)), DEVMODE)
Dim lngSaveSize As Long = _
testDevmode.dmSize + testDevmode.dmDriverExtra
ReDim bytReadBuf(lngSaveSize)
Marshal.Copy(globalDevOut, bytReadBuf, 0, lngSaveSize)
GlobalUnlock(PtrDevMode)
GlobalFree(PtrDevMode)
Dim fs As New FileStream("c:\\test.obj", _
FileMode.Create, FileAccess.Write)
Dim bw As New BinaryWriter(fs)
bw.Write(bytReadBuf, 0, lngSaveSize)
bw.Close()
fs.Close()
End Sub
|
コード: |
|
Public Shared Function LoadFromBinaryFile(ByVal path As String) _
As PrinterSettings
Dim dsp As New PrinterSettings()
Dim testDevmode As New DEVMODE
Dim bytReadBuf(2036) As Byte
Dim PtrDevMode As IntPtr
Dim fs As New FileStream(path, FileMode.Open, FileAccess.Read)
Dim br As New BinaryReader(fs)
PtrDevMode = dsp.GetHdevmode(dsp.DefaultPageSettings)
Dim globalDevOut As IntPtr = GlobalLock(PtrDevMode)
Dim ptr As IntPtr = _
Marshal.AllocHGlobal(Marshal.SizeOf(testDevmode))
Try
ReDim bytReadBuf(Marshal.SizeOf(testDevmode))
bytReadBuf = br.ReadBytes(Marshal.SizeOf(testDevmode))
Marshal.Copy(bytReadBuf, 0, ptr, Marshal.SizeOf(testDevmode))
testDevmode = _
DirectCast(Marshal.PtrToStructure(ptr, GetType(DEVMODE)), _
DEVMODE)
Dim lngSaveSize As Long = _
testDevmode.dmSize + testDevmode.dmDriverExtra
fs.Position = 0
ReDim bytReadBuf(lngSaveSize)
bytReadBuf = br.ReadBytes(lngSaveSize)
Marshal.Copy(bytReadBuf, 0, globalDevOut, lngSaveSize)
dsp.DefaultPageSettings.SetHdevmode(globalDevOut)
dsp.SetHdevmode(globalDevOut)
Catch ex As Exception
Finally
GlobalUnlock(PtrDevMode)
GlobalFree(PtrDevMode)
If IntPtr.Zero <> ptr Then
Marshal.FreeHGlobal(ptr)
End If
br.Close()
fs.Close()
End Try
Return dsp
End Function
|
よろしくお願いします。
//リゾナンス 水穂和明
|
- 未記入
- ぬし
- 会議室デビュー日: 2004/09/17
- 投稿数: 667
|
投稿日時: 2008-01-07 20:56
引用: |
|
Dim testDevmode As New DEVMODE
Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(testDevmode))
Marshal.Copy(bytReadBuf, 0, ptr, Marshal.SizeOf(testDevmode))
|
LoadFromBinaryFile の、この辺がおかしいんじゃない? もう一度、同じこと言うけど、DEVMODE 構造体は末尾にプライベート領域があるためサイズが固定ではありません。プライベート領域の分もちゃんとメモリを確保して。プライベート領域の分もちゃんと読み込んで。
|
- 水穂和明
- 会議室デビュー日: 2001/12/25
- 投稿数: 6
- お住まい・勤務地: 鳥取県米子市
|
投稿日時: 2008-01-07 22:00
引用の部分ですが…。
一度DEVMODE構造体のサイズ分のデータをファイルより読み込み、DEVMODE構造体のメンバよりサイズを求めてもう一度ファイルの先頭より(DEVMODE構造体のサイズ+プライベート領域のサイズ)のサイズでByte()に読み込んでいるつもりですが…。
コメントが入ってなくて大変読みにくいコードで申し訳ありませんでした。
ちなみにここら辺です。
引用: |
|
Dim lngSaveSize As Long = _
testDevmode.dmSize + testDevmode.dmDriverExtra
fs.Position = 0
ReDim bytReadBuf(lngSaveSize)
bytReadBuf = br.ReadBytes(lngSaveSize)
Marshal.Copy(bytReadBuf, 0, globalDevOut, lngSaveSize)
|
|