C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

DEVMODEの値を変更したい


(過去ログ 2 を表示中)

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■2377 / inTopicNo.1)  DEVMODEの値を変更したい
  
□投稿者/ あや 二等兵(1回)-(2006/01/25(Wed) 10:29:04)

分類:[C#] 


分類:[C#] 

はじめまして。

C#にて印刷プログラムの開発をしていますが、プリンタ固有の情報を変更するため、DEVMODEの値を変更する必要があります。
PrinterSettingsクラスにGetHdevmode、SetHdevmodeというメソッドがあるので、これが使用できるかと思うのですが、使用方法が全くわかりません。

 public void Print() {
   // DEVMODEを取得する
   IntPtr devmode = this.printDocument.PrinterSettings.GetHdevmode();

   // プリンタ固有の値を変更する
   // DEVMODEの値を変更したいのですが使用方法がわかりません

   // 変更したDEVMODEを設定する
   this.printDocument.PrinterSettings.SetHdevmode(devmode);
 }

MSDNにもサンプルが載っておらず困っています。何かよい方法がありましたらアドバイスお願いします。


0
引用返信 編集キー/
■2377 / inTopicNo.2)  DEVMODEの値を変更したい
□投稿者/ あや 二等兵(1回)-(2006/01/25(Wed) 10:29:04)

分類:[C#] 


分類:[C#] 

はじめまして。

C#にて印刷プログラムの開発をしていますが、プリンタ固有の情報を変更するため、DEVMODEの値を変更する必要があります。
PrinterSettingsクラスにGetHdevmode、SetHdevmodeというメソッドがあるので、これが使用できるかと思うのですが、使用方法が全くわかりません。

 public void Print() {
   // DEVMODEを取得する
   IntPtr devmode = this.printDocument.PrinterSettings.GetHdevmode();

   // プリンタ固有の値を変更する
   // DEVMODEの値を変更したいのですが使用方法がわかりません

   // 変更したDEVMODEを設定する
   this.printDocument.PrinterSettings.SetHdevmode(devmode);
 }

MSDNにもサンプルが載っておらず困っています。何かよい方法がありましたらアドバイスお願いします。


0
引用返信 編集キー/
■2380 / inTopicNo.3)  Re[1]: DEVMODEの値を変更したい
□投稿者/ T★M 二等兵(1回)-(2006/01/25(Wed) 11:36:22)

分類:[C#] 

この辺り?
http://www.microsoft.com/JAPAN/developer/library/vcmfc/_mfc_devmode_structure.htm

0
引用返信 編集キー/
■2380 / inTopicNo.4)  Re[1]: DEVMODEの値を変更したい
□投稿者/ T★M 二等兵(1回)-(2006/01/25(Wed) 11:36:22)

分類:[C#] 

この辺り?
http://www.microsoft.com/JAPAN/developer/library/vcmfc/_mfc_devmode_structure.htm

0
引用返信 編集キー/
■2382 / inTopicNo.5)  Re[2]: DEVMODEの値を変更したい
□投稿者/ Hongliang 二等兵(2回)-(2006/01/25(Wed) 12:12:13)

分類:[C#] 

手順的には、

・C#側でDEVMODE構造体を定義しておく。
・GetHdevmodeメソッドでハンドルを取得する。
・Win32APIのGlobalLock関数で、ハンドルからアドレスポインタを取得する。
・System.Runtime.InteropServices.Marshal.PtrToStructureメソッドでポインタから構造体にコピーする。
・構造体を変更する。
・同じアドレスにMarshal.StructureToPtrメソッドでコピーする。
・Win32APIのGlobalUnlock関数でロックを解放。
・SetHdevmodeメソッドで書き込む。
・Win32APIのGlobalFree関数でメモリを解放する。

ってことになりますかね。
DEVMODE構造体のC#における表現はPINVOKE.NET辺り見ると載ってるかもしれません。
プリンタ固有ってことはこの構造体の後ろにくっついてるんだろうけど、それらについてはMarshal.Read.../Write...メソッドを使うとかしないといけないかもしれません。

0
引用返信 編集キー/
■2382 / inTopicNo.6)  Re[2]: DEVMODEの値を変更したい
□投稿者/ Hongliang 二等兵(2回)-(2006/01/25(Wed) 12:12:13)

分類:[C#] 

手順的には、

・C#側でDEVMODE構造体を定義しておく。
・GetHdevmodeメソッドでハンドルを取得する。
・Win32APIのGlobalLock関数で、ハンドルからアドレスポインタを取得する。
・System.Runtime.InteropServices.Marshal.PtrToStructureメソッドでポインタから構造体にコピーする。
・構造体を変更する。
・同じアドレスにMarshal.StructureToPtrメソッドでコピーする。
・Win32APIのGlobalUnlock関数でロックを解放。
・SetHdevmodeメソッドで書き込む。
・Win32APIのGlobalFree関数でメモリを解放する。

ってことになりますかね。
DEVMODE構造体のC#における表現はPINVOKE.NET辺り見ると載ってるかもしれません。
プリンタ固有ってことはこの構造体の後ろにくっついてるんだろうけど、それらについてはMarshal.Read.../Write...メソッドを使うとかしないといけないかもしれません。

0
引用返信 編集キー/
■2383 / inTopicNo.7)  Re[2]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(3回)-(2006/01/25(Wed) 12:27:48)

分類:[C#] 

説明不足ですいません。

DEVMODE構造体はわかっているつもりです。
お聞きしたいのは、GetHdevmodeから返ってくるのがIntPtrなので、これをどうやって
DEVMODE構造体にするのかと、ドライバ固定の値をどうやって設定するのかということです。

お手数かけますが、よろしくお願いします。

0
引用返信 編集キー/
■2383 / inTopicNo.8)  Re[2]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(3回)-(2006/01/25(Wed) 12:27:48)

分類:[C#] 

説明不足ですいません。

DEVMODE構造体はわかっているつもりです。
お聞きしたいのは、GetHdevmodeから返ってくるのがIntPtrなので、これをどうやって
DEVMODE構造体にするのかと、ドライバ固定の値をどうやって設定するのかということです。

お手数かけますが、よろしくお願いします。

0
引用返信 編集キー/
■2386 / inTopicNo.9)  Re[3]: DEVMODEの値を変更したい
□投稿者/ 中博俊 大将(291回)-(2006/01/25(Wed) 12:54:47)
中博俊 さんの Web サイト

分類:[C#] 

とりあえず私が断念した内容と同じ(w

すなおにmc++ or C++/CLIでラップするのが近道だと思います。

0
引用返信 編集キー/
■2386 / inTopicNo.10)  Re[3]: DEVMODEの値を変更したい
□投稿者/ 中博俊 大将(291回)-(2006/01/25(Wed) 12:54:47)
中博俊 さんの Web サイト

分類:[C#] 

とりあえず私が断念した内容と同じ(w

すなおにmc++ or C++/CLIでラップするのが近道だと思います。

0
引用返信 編集キー/
■2389 / inTopicNo.11)  Re[3]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(4回)-(2006/01/25(Wed) 13:13:58)

分類:[C#] 

レスが前後してしまったようで・・・

Hongliangさんのアドバイスを元にもうちょっと調べてみようと思います。
また何かありましたらよろしくお願いします。


0
引用返信 編集キー/
■2389 / inTopicNo.12)  Re[3]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(4回)-(2006/01/25(Wed) 13:13:58)

分類:[C#] 

レスが前後してしまったようで・・・

Hongliangさんのアドバイスを元にもうちょっと調べてみようと思います。
また何かありましたらよろしくお願いします。


0
引用返信 編集キー/
■2392 / inTopicNo.13)  Re[4]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(7回)-(2006/01/25(Wed) 17:45:20)

分類:[C#] 

Hongliangさんのアドバイスを元にとりあえずDEVMODEを取得するところからチャレンジしてみたのですが、取得するたびにDEVMODEの内容が少しずつ違うのですが・・・
以下ソースと結果ですが、何か間違っているところはあるでしょうか?(DEVMODEの定義はPINVOKE.NETを参考にさせていただきました)

  [StructLayout(LayoutKind.Sequential)]
  public struct DEVMODE {
   [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
   public string dmDeviceName;
   public short dmSpecVersion;
   public short dmDriverVersion;
   public short dmSize;
   public short dmDriverExtra;
   public int dmFields;
   public short dmOrientation;
   public short dmPaperSize;
   public short dmPaperLength;
   public short dmPaperWidth;
   public short dmScale;
   public short dmCopies;
   public short dmDefaultSource;
   public short dmPrintQuality;
   public short dmColor;
   public short dmDuplex;
   public short dmYResolution;
   public short dmTTOption;
   public short dmCollate;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
   public string dmFormName;
   public short dmLogPixels;
   public short dmBitsPerPel;
   public int dmPelsWidth;
   public int dmPelsHeight;
   public int dmDisplayFlags;
   public int dmDisplayFrequency;
   public int dmICMMethod;
   public int dmICMIntent;
   public int dmMediaType;
   public int dmDitherType;
   public int dmReserved1;
   public int dmReserved2;
   public int dmPanningWidth;
   public int dmPanningHeight;
  };

  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalFree(IntPtr hMem);

  private void btnTest_Click(object sender, System.EventArgs e) {
   IntPtr devmodePtr = this.printDocument.PrinterSettings.GetHdevmode();
   DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(devmodePtr, typeof(DEVMODE));
   GlobalFree(devmodePtr);

   Debug.WriteLine("dm.dmDeviceName[" + dm.dmDeviceName + "]");
   Debug.WriteLine("dm.dmSpecVersion[" + dm.dmSpecVersion + "]");
   Debug.WriteLine("dm.dmDriverVersion[" + dm.dmDriverVersion + "]");
   Debug.WriteLine("dm.dmSize[" + dm.dmSize + "]");
   Debug.WriteLine("dm.dmDriverExtra[" + dm.dmDriverExtra + "]");
}

結果1回目
 dm.dmDeviceName[ !]
 dm.dmSpecVersion[0]
 dm.dmDriverVersion[0]
 dm.dmSize[144]
 dm.dmDriverExtra[981]

結果2回目
 dm.dmDeviceName[ p・p]
 dm.dmSpecVersion[0]
 dm.dmDriverVersion[0]
 dm.dmSize[136]
 dm.dmDriverExtra[981]

長くなってしまいましたが、よろしくお願いします。

0
引用返信 編集キー/
■2392 / inTopicNo.14)  Re[4]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(7回)-(2006/01/25(Wed) 17:45:20)

分類:[C#] 

Hongliangさんのアドバイスを元にとりあえずDEVMODEを取得するところからチャレンジしてみたのですが、取得するたびにDEVMODEの内容が少しずつ違うのですが・・・
以下ソースと結果ですが、何か間違っているところはあるでしょうか?(DEVMODEの定義はPINVOKE.NETを参考にさせていただきました)

  [StructLayout(LayoutKind.Sequential)]
  public struct DEVMODE {
   [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
   public string dmDeviceName;
   public short dmSpecVersion;
   public short dmDriverVersion;
   public short dmSize;
   public short dmDriverExtra;
   public int dmFields;
   public short dmOrientation;
   public short dmPaperSize;
   public short dmPaperLength;
   public short dmPaperWidth;
   public short dmScale;
   public short dmCopies;
   public short dmDefaultSource;
   public short dmPrintQuality;
   public short dmColor;
   public short dmDuplex;
   public short dmYResolution;
   public short dmTTOption;
   public short dmCollate;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
   public string dmFormName;
   public short dmLogPixels;
   public short dmBitsPerPel;
   public int dmPelsWidth;
   public int dmPelsHeight;
   public int dmDisplayFlags;
   public int dmDisplayFrequency;
   public int dmICMMethod;
   public int dmICMIntent;
   public int dmMediaType;
   public int dmDitherType;
   public int dmReserved1;
   public int dmReserved2;
   public int dmPanningWidth;
   public int dmPanningHeight;
  };

  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalFree(IntPtr hMem);

  private void btnTest_Click(object sender, System.EventArgs e) {
   IntPtr devmodePtr = this.printDocument.PrinterSettings.GetHdevmode();
   DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(devmodePtr, typeof(DEVMODE));
   GlobalFree(devmodePtr);

   Debug.WriteLine("dm.dmDeviceName[" + dm.dmDeviceName + "]");
   Debug.WriteLine("dm.dmSpecVersion[" + dm.dmSpecVersion + "]");
   Debug.WriteLine("dm.dmDriverVersion[" + dm.dmDriverVersion + "]");
   Debug.WriteLine("dm.dmSize[" + dm.dmSize + "]");
   Debug.WriteLine("dm.dmDriverExtra[" + dm.dmDriverExtra + "]");
}

結果1回目
 dm.dmDeviceName[ !]
 dm.dmSpecVersion[0]
 dm.dmDriverVersion[0]
 dm.dmSize[144]
 dm.dmDriverExtra[981]

結果2回目
 dm.dmDeviceName[ p・p]
 dm.dmSpecVersion[0]
 dm.dmDriverVersion[0]
 dm.dmSize[136]
 dm.dmDriverExtra[981]

長くなってしまいましたが、よろしくお願いします。

0
引用返信 編集キー/
■2395 / inTopicNo.15)  Re[4]: DEVMODEの値を変更したい
□投稿者/ Hongliang 二等兵(3回)-(2006/01/25(Wed) 20:13:55)
Hongliang さんの Web サイト

分類:[C#] 

大事なところを読み飛ばさないでください〜。

・Win32APIのGlobalLock関数で、ハンドルからアドレスポインタを取得する。

GetHdevmodeで取得できるのは「ハンドル」です。ポインタじゃありません。
//ポインタのポインタ、みたいなものです。
だからこの値(が表すアドレス)に直接構造体を割り当てても意味ありません。
ハンドルからポインタを取得するのにGlobalLockが必要なのです。
もちろん使い終わったらGlobalUnlockも忘れずに。

それから、恐らくこの構造体では文字セットの問題が発生すると思います。
GetHdevmodeが内部で呼び出しているのは(私が試した限り)NT系ではW系の関数です。つまりデバイス名とフォーム名がUnicodeで返されています。
StructLayout属性はデフォルトではCharSetがAnsiに設定されていますから、文字列へのマーシャリングで失敗するでしょう。
プラットフォームにあう文字セットを使用するように、StructLayout属性のCharSetフィールドをAutoに設定してください。

0
引用返信 編集キー/
■2395 / inTopicNo.16)  Re[4]: DEVMODEの値を変更したい
□投稿者/ Hongliang 二等兵(3回)-(2006/01/25(Wed) 20:13:55)
Hongliang さんの Web サイト

分類:[C#] 

大事なところを読み飛ばさないでください〜。

・Win32APIのGlobalLock関数で、ハンドルからアドレスポインタを取得する。

GetHdevmodeで取得できるのは「ハンドル」です。ポインタじゃありません。
//ポインタのポインタ、みたいなものです。
だからこの値(が表すアドレス)に直接構造体を割り当てても意味ありません。
ハンドルからポインタを取得するのにGlobalLockが必要なのです。
もちろん使い終わったらGlobalUnlockも忘れずに。

それから、恐らくこの構造体では文字セットの問題が発生すると思います。
GetHdevmodeが内部で呼び出しているのは(私が試した限り)NT系ではW系の関数です。つまりデバイス名とフォーム名がUnicodeで返されています。
StructLayout属性はデフォルトではCharSetがAnsiに設定されていますから、文字列へのマーシャリングで失敗するでしょう。
プラットフォームにあう文字セットを使用するように、StructLayout属性のCharSetフィールドをAutoに設定してください。

0
引用返信 編集キー/
■2397 / inTopicNo.17)  Re[5]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(9回)-(2006/01/26(Thu) 11:50:58)

分類:[C#] 

肝心なところを見逃してしまい大変申し訳ありませんでした m(__)m
(決して意図的ではありませんのでご勘弁を・・・)

再度内容を確認し、以下のようにすることで読み書きができました。
勉強不足のためまだ不安なところがありますが、ひとまず動くようになりましたのでホッとしています。

以下、現在のソースと不安なところです。

  # APIの宣言と、ロックを解放〜に自信がありません。
  # GlobalUnlock()、SetHdevmode()、GlobalFree()の引数はhMemでいいのでしょうか?
  # 私が試した限りでは、devmodePtrでも正しく動作しています。

  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
  public struct DEVMODE {
      ・・・
  };

  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalLock(IntPtr hMem);
  [DllImport("kernel32.dll")]
  private static extern bool GlobalUnlock(IntPtr hMem);
  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalFree(IntPtr hMem);

  private void btnTest_Click(object sender, System.EventArgs e) {
   IntPtr hMem = this.printDocument.PrinterSettings.GetHdevmode(); // ハンドル取得
   IntPtr devmodePtr = GlobalLock(hMem); // ロック・ハンドルからポインタを取得
   DEVMODE dm =
       (DEVMODE)Marshal.PtrToStructure(devmodePtr, typeof(DEVMODE)); // ポインタから構造体にコピー

   dm.dmCopies = 10; // 印刷部数を10部に設定
   dm.dmCollate = 1; // 部単位で印刷
   Marshal.WriteByte(devmodePtr, dm.dmSize+720, 0); // ドライバ固定の720Byte目を0
   Marshal.StructureToPtr(dm, devmodePtr, true); // 構造体からポインタにコピー

   GlobalUnlock(hMem); // ロックを解放
   this.printDocument.PrinterSettings.SetHdevmode(hMem); // PriterSetteingsにコピー
   GlobalFree(hMem); // ハンドルを解放
  }

よろしくお願いします。


0
引用返信 編集キー/
■2397 / inTopicNo.18)  Re[5]: DEVMODEの値を変更したい
□投稿者/ あや 二等兵(9回)-(2006/01/26(Thu) 11:50:58)

分類:[C#] 

肝心なところを見逃してしまい大変申し訳ありませんでした m(__)m
(決して意図的ではありませんのでご勘弁を・・・)

再度内容を確認し、以下のようにすることで読み書きができました。
勉強不足のためまだ不安なところがありますが、ひとまず動くようになりましたのでホッとしています。

以下、現在のソースと不安なところです。

  # APIの宣言と、ロックを解放〜に自信がありません。
  # GlobalUnlock()、SetHdevmode()、GlobalFree()の引数はhMemでいいのでしょうか?
  # 私が試した限りでは、devmodePtrでも正しく動作しています。

  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
  public struct DEVMODE {
      ・・・
  };

  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalLock(IntPtr hMem);
  [DllImport("kernel32.dll")]
  private static extern bool GlobalUnlock(IntPtr hMem);
  [DllImport("kernel32.dll")]
  private static extern IntPtr GlobalFree(IntPtr hMem);

  private void btnTest_Click(object sender, System.EventArgs e) {
   IntPtr hMem = this.printDocument.PrinterSettings.GetHdevmode(); // ハンドル取得
   IntPtr devmodePtr = GlobalLock(hMem); // ロック・ハンドルからポインタを取得
   DEVMODE dm =
       (DEVMODE)Marshal.PtrToStructure(devmodePtr, typeof(DEVMODE)); // ポインタから構造体にコピー

   dm.dmCopies = 10; // 印刷部数を10部に設定
   dm.dmCollate = 1; // 部単位で印刷
   Marshal.WriteByte(devmodePtr, dm.dmSize+720, 0); // ドライバ固定の720Byte目を0
   Marshal.StructureToPtr(dm, devmodePtr, true); // 構造体からポインタにコピー

   GlobalUnlock(hMem); // ロックを解放
   this.printDocument.PrinterSettings.SetHdevmode(hMem); // PriterSetteingsにコピー
   GlobalFree(hMem); // ハンドルを解放
  }

よろしくお願いします。


0
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -