いつも勉強させていただいております。
現在、あるプリンタードライバの制御を行おうと、C言語のサンプルから
Delphi(5.0)を作成しているのですが、私C言語が全く無知の為、
下記のように記述しているのですが、上手く動いてくれません。
もしご存知の方がいらっしゃいましたら、お教えいただきたいと思います。
【C言語サンプル】
typedef struct{
CHAR szPrinterName[256];
CHAR szDriverName[256];
WORD wSpecVersion;
WORD wDriverVersion;
LPDEVMODE pDevmode;
}FXPRNINFO,FAR * LPFXPRNINFO;
↓
【Delphiへ】
type fxPRNINFO = record
szPrinterName : array[1..256] of Char;
szDriverName : array[1..256] of Char;
wSpecVersion : Word;
wDriverVersion : Word;
pDevmode : ^Int64;
end;
var
lpprninfo : fxPRNINFO;
宜しくお願いします。
主目的がC言語との対比なのか(タイトルがそうなっているので)、
プリンタードライバの制御なのか、
プリンタードライバの制御とはどのような内容なのか、
上手く動かないというのが、どのような状態なのかはわかりませんが、
「プリンタの制御/印刷」用で有名なNkPrinterというのがあります。
このコードが参考になりませんでしょうか。
既にネット上で検索して確認済みでしたらご容赦下さい。
http://www.asahi-net.or.jp/%7EHA3T-NKMR/deldown.htm
typedef struct{
CHAR szPrinterName[256];
CHAR szDriverName[256];
WORD wSpecVersion;
WORD wDriverVersion;
LPDEVMODE pDevmode;
}FXPRNINFO,FAR * LPFXPRNINFO;
structは構造体のことですね。
charは1byteの文字のことですね。
WORDは2byte符号付整数だったような(悩
#検索すれば見つかりますね。
LPDEVMODE、名前から察するに、何かのポインタですね。
("pDevmode : ^Int64;"とか書いているんで、long long型でしょうか)
FXPRNINFO,FAR * LPFXPRNINFOは、構造体の名前とその型のポインタですね。
うまく動かないとはどのような現象か分かりませんが、
DLLでも呼び出しているんでしょうか。
#そもそも、ヘッダファイルのdelphiへの移植が間違っているとお思いなのでしょうか。
#最小限のコードの提示を行えば、誰かが答えてくれる可能性が高いですよ。
Mr.XRAYさん、Cさんご返信誠にありがとうございます。
説明不足で申し訳ありません。
行いたいことは、PSLAD2を使用して、FX Docu Centre 320のプリンタードライバー(FAX送信用)の内容(宛先一覧に残っているFAX番号全て)をクリアしたいと思っているのですが、
PSLADのメーカーにも問合せたのですが、ソースの解析までは行わないということで行き詰ってしまいました。
Delphiのソースは下記のとおりなのですが、
if (fxPAPI_Get(hAPI,lpPrninfo)) = True then
でFalseが返ってきます。
エラーの内容は
【プリンター情報を設定する構造体が指定されていません】で
メーカーに問い合わせたところ
2番目のパラメータが渡されていない事(NULLポインタが
設定されています。)を意味しております。
正しく、FXPRNINFO構造体のポインタ(アドレス)を引数としているか
どうかをご確認ください。
その他、変数の型など、誤りがないか再度ご確認願います。
の返信があったのですが、何がどう悪いか良く解らない状態に陥って
しまいました。
以上宜しくお願いします。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Db, ComCtrls, ExtCtrls, OleCtrls, CoReports_TLB, ComUnit,
Buttons, MFREMOTELib_TLB;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
Ini_FaxDriver: string;
end;
//===== PSLADライブラリの構造体宣言
type fxPRNINFO = record
szPrinterName : array[1..256] of Char;
szDriverName : array[1..256] of Char;
wSpecVersion : Word;
wDriverVersion : Word;
pDevmode : ^Int64;
end;
var
Form1: TForm1;
const
PATH_INI_FILE = 'C:\TEST.INI'; // INIファイル
DllName = 'PSLAD32.dll';
Function fxPAPI_Create(hWnd: THandle; printerName: String; iDBSwitch: Integer): integer;
stdcall;external DllName;
Function fxPAPI_Set(hAPI: Longint; STR: String): Boolean;
stdcall;external DllName;
Function fxPAPI_Destroy(hAPI: Longint): Boolean;
stdcall;external DllName;
Function fxPAPI_Get(hAPI: LongInt; lpPrninfo: fxPRNINFO): Boolean;
stdcall;external DllName;
Function fxPAPI_CreateDC(hAPI: Longint): Integer;
stdcall;external DllName;
Function fxPAPI_DeleteDC(hAPI, hdc:Longint): Boolean;
stdcall;external DllName;
Function fxPAPI_SetDefaultPrinter(hAPI:Longint; bFlag:Boolean): Boolean;
stdcall;external DllName;
Function fxPAPI_ResetDefaultPrinter(hAPI:Longint): Boolean;
stdcall;external DllName;
Function fxPAPI_SetFaxShowDialog(hAPI:Longint; bFlag:Boolean): Boolean;
stdcall;external DllName;
Function fxPAPI_Reset(hAPI:Longint; FaxNum:String): Boolean;
stdcall;external DllName;
implementation
{$R *.dfm}
var
hAPI : Longint;
WkStr : string;
lpprninfo : fxPRNINFO;
hdc : Integer;
INI_SL : TStringList;
IniName : string;
plDevmode : int64;
procedure TForm1.Button1Click(Sender: TObject);
begin
//INIファイル読み込み
INI_SL:=TStringList.Create;
IniName := PATH_INI_FILE;
if FileExists(IniName) = False then
begin
MessageDlg('INI File(' + IniName + ')が存在しません。', mtInformation, [mbOK], 0);
exit;
end;
INI_SL.LoadFromFile(IniName); //INIファイルload
Ini_FaxDriver:=INI_SL.Values['FaxDriver'];
hAPI:=fxPAPI_Create(0, 'FX DocuCentre Color 320 FAX', 1);
if hAPI = 0 then //初期化に失敗した時
begin
ShowMessage('FAX送信に失敗しました(Create)');
exit;
end;
if (fxPAPI_Get(hAPI,lpPrninfo)) = True then
begin
if (fxPAPI_Reset(hAPI,'FaxToNum')) = True then
begin
if (fxPAPI_SetDefaultPrinter(hAPI,True)) = True then
begin
if (fxPAPI_Destroy(hAPI)) = False then
begin
ShowMessage('Destoryエラー');
end;
end;
end;
end;
self.close;
end;
end.
ちらちら見ての、考えですが。。。
(説明時の用語が間違っている可能性がありますが、ご容赦を)
Function fxPAPI_Get(hAPI: LongInt; lpPrninfo: fxPRNINFO): Boolean;
stdcall;external DllName;
上の関数の第2引数は、ポインタを渡すんでしょうか。
であるならば、実体を渡しているように見えます。
つまり、@演算子を使用する?
if (fxPAPI_Get(hAPI,@lpPrninfo)) = True then
あと、DLLの呼び出し(動的呼び出し)は行わないでいいのでしょうか。
Delphiって、静的呼び出しができるのでしょうか。
手元にdelphiがないので確認できませんがwindows.pasあたりにTDevModeの型が宣言されているとおもいます。
その場合、pDevmode : ^Int64は
pDevmode: ^TDevMode;になります。
fxPAPI_Getは見た限り宣言の型が違う気がします。
大抵lpと付くとポインタを要求しますので
fxPAPI_Get(hAPI: LongInt; lpPrninfo: ^fxPRNINFO): Boolean
と変えて、引数の渡し方をCさんが書かれているように、アドレス渡しにしてみるとどうでしょうか。
Cさん
externalでDLLNameのDLLにあると宣言してますので静的にリンクされます。
>pDevmode: ^TDevMode;になります。
TDevModeって構造体か何かでしょうか。
>fxPAPI_Get(hAPI: LongInt; lpPrninfo: ^fxPRNINFO): Boolean
>と変えて、
元のC言語のヘッダファイルを見ればすぐに分かりますね。
型 * 変数名;
となっていれば、ポインタを宣言しています。<-しゅうさん。
>externalでDLLNameのDLLにあると宣言してますので静的にリンクされます。
なるほど、知りませんでした(^^;a
けれど、動的にしたほうがいいかもしれませんね。
DLLが存在しない場合、起動せずにクリティカルエラーを出しますし。。。
>>pDevmode: ^TDevMode;になります。
>TDevModeって構造体か何かでしょうか。
すみません、自分で調べてしまいました。
構造体ですね。
やたら長い。。。
ご返信遅れ申し訳ありません。
Cさんskさん、誠にありがとうございます。
早速お教え頂いた内容で試してみます。
結果わかりましたらご報告させて頂きます。
Cさんskさん
ご教授頂戴したとおり幾つか試してみました。
①(要所だけソースを記載します)
//===== PSLADライブラリの構造体宣言
type fxPRNINFO = Record
szPrinterName : array[1..256] of Char;
szDriverName : array[1..256] of Char;
wSpecVersion : Word;
wDriverVersion : Word;
pDevmode: ^TDevMode; ←ここを変更
end;
Function fxPAPI_Get(hAPI: THandle; lpPrninfo: ^fxPRNINFO): Boolean;
stdcall;external DllName; ↑ここを変更
var
hAPI: THandle;
lpPrninfo: fxPRNINFO;
if (fxPAPI_Get(hAPI,@lpPrninfo)) = True then
↑ここを変更
そうしますと、コンパイルエラーで
[エラー] Unit1.pas(97): 'fxPRNINFO' と 'Pointer' には互換性がありません と表示されます。
そこで
②
//===== PSLADライブラリの構造体宣言
type ^fxPRNINFO = Record ←ここを変更
szPrinterName : array[1..256] of Char;
szDriverName : array[1..256] of Char;
wSpecVersion : Word;
wDriverVersion : Word;
pDevmode: ^TDevMode; ←ここを変更
end;
Function fxPAPI_Get(hAPI: THandle; lpPrninfo: ^fxPRNINFO): Boolean;
stdcall;external DllName; ↑ここを変更
var
hAPI: THandle;
lpPrninfo: ^fxPRNINFO;→ここを変更
if (fxPAPI_Get(hAPI,@lpPrninfo)) = True then
↑ここを変更
しますと
[エラー] Unit1.pas(24): 識別子 が必要な場所に '^' があります
(typeの^fxPRNINFOでエラー)
となってしましまいます。
何度も申し訳ありませんが、原因がありましたらお教え頂ければ
助かります。
type
pfxPRNINFO = ^fxPRNINFO;
fxPRNINFO = record
szPrinterName : array[1..256] of Char;
szDriverName : array[1..256] of Char;
wSpecVersion : Word;
wDriverVersion : Word;
pDevmode: ^TDevMode;
end;
function fxPAPI_Get(hAPI: THandle; lpPrninfo: pfxPRNINFO): boolean;
var
prninfo: fxPRNINFO;
begin
fxPAPI_Get(hAPI, addr(prninfo));
これでどうでしょうか。
Cサンプルのプロトタイプ宣言と呼び出しのところを乗せてもらえると話が早いです。
skさん
誠にありがとうございます。
お教え頂いた内容で、Get命令にはTrueが返ってきました。
ありがとうございました。
しかしながら、未だドライバーの内容がクリアされないようで(^-^;
もう少し調べてみます。
ちなみに、C言語の記述は下記のとおりです。
// ライブラリで使用する構造体の宣言
typedef struct { // fxPAPI_Get関数で取得する情報の構造体
CHAR szPrinterName[256];
CHAR szDriverName[256];
WORD wSpecVersion;
WORD wDriverVersion;
LPDEVMODE pDevmode; // DEVMODE構造体のポインタ
} FXPRNINFO, FAR * LPFXPRNINFO;
BOOL WINAPI fxPAPI_Get( // DEVMODE構造体の情報を取得
HAPI hAPI, // ライブラリのハンドル
LPFXPRNINFO lpfxPrnInfo // プリンタ情報
すみません、これで解りますでしょうか?
>お教え頂いた内容で、Get命令にはTrueが返ってきました。
できたみたいで、良かったですね。
>しかしながら、未だドライバーの内容がクリアされないようで(^-^;
クリアの意味が分かりません。
fxPAPI_Get関数の質問ですよね。
見た感じで、何かのデータを取得する関数のようですが。。。
最初の質問と違うのですか。
Cさんへ
すみません、最初の質問以外の発言をしてしまいまして。
fxPAPI_Get関数発行後、fxPAPI_Reset(hAPI,'FaxToNum')で
ドライバーの設定値をクリアするはずなのですが、
(FaxToNumは送り先FAX番号を示します)クリアされないようなのです。
何度も誠に申し訳ありませんが、何か気になられることがありましたら
ご教授下さい。
Function fxPAPI_Reset(hAPI:Longint; FaxNum:String): Boolean;
や、他の関数でstringになっているのはPCharにすべきでしょう。
あとは今の情報からだとわかりません。(送り先番号が'FaxToNum'なんて文字列でいいのかってのがありますが)
リセットがされてないという言い方では、fxPAPI_ResetでFalseが帰ってくるのか、どこかのデータが書き換わってないのかがわかりません。
>Function fxPAPI_Reset(hAPI:Longint; FaxNum:String): Boolean;
>や、他の関数でstringになっているのはPCharにすべきでしょう。
そうですね。
(って、同意しかしてない。。。)
C言語的に言わせていただくと、
C言語にはString型のような文字列型は存在しません。
文字型(char型)の配列(NULL終端)で表します。
skさんCさん
色々ご教授頂き誠にありがとうございます。
FAXナンバーがクリアされていないといいますのが、
DOCUCENTREのFAXプリンタードライバー上に残っているFAX番号を消したいと
思っています。
PSLAD2のマニュアルを見ますと、
fxPAPI_Reset(hAPI:Longint; FaxNum:String): Boolean
となっており、FaxNumに'FaxToNum'という文字列を送ると、クリアされる
ように書いているようなのです。
なお、Reset関数ではTrueが返ってきます。
ちなみに、下記にマニュアルの抜粋を載せます。
fxPAPI_Rset関数について
呼び出し方法
BOOL fxPAPI_Reset(HAPI hAPI,LPSRT command);
引数 hAPI
fxPAPI_Create関数により取得したHAPI(ハンドル)
command
DEVMODE構造体をクリアする為の情報を設定するコマンド
文字列
戻り値:指定されたcommand文字列の設定項目が全て正しく設定
出来た場合にTrueを返します。
fxPAPI_Reset関数コマンドの詳細
6.5章で記述したようにfxPAPI_Reset関数のcommand文字列は
キーワードをカンマで繋げて指定します。
例:"FaxToName,FaxToAddinfo"
この章ではfxPAPI_Reset関数で指定するcommandの文字列の使用を
キーワード別に記述します。
9.1. FaxToNum
動作:内線指定、外線指定、回線指定なしで指定した全てのファックス番号及び、ファックス送信先の通性設定をクリアします。
以上参考程度にしかならないと思いますが、何かございましたらご教授下さい。
宜しくお願いいたします。
fxPAPI_Resetでtrueが帰ってきてるならクリアできてるんではないでしょうか。
クリアされてるかどうかは、どうやって確認していますか?
skさんへ
クリアされているかどうかの判断なのですが、
DocuCentreのプリンターを右クリックして印刷設定を選択しますと
FAXの送信情報画面が表示されます。
その中の宛先一覧のグリッド内にFAX番号が残ったままになっている
ので、クリア出来ていないのではないかと......(^-^;
PSLADのメーカーに問い合わせると、C言語,VBではクリアされていますとの
返答が帰ってきました。
わかりずらいかもしれませんが、宜しくお願いいたします。
> PSLADのメーカーに問い合わせると、C言語,VBではクリアされていますとの
> 返答が帰ってきました。
されてなかったらバグだっての(笑)
> fxPAPI_Reset(hAPI:Longint; FaxNum:String): Boolean
> となっており、FaxNumに'FaxToNum'という文字列を送ると、クリアされる
> ように書いているようなのです。
「書いてるようなの」って、それこそ「消えるものなのか」メーカーに確認してみたらいいのでは?
http://www.acel.co.jp/solutions/topic_PD_pslad2_freedownload.html
なんか、ここからLight版のライブラリをダウンロードできるっぽいのですが、
関数の定義の仕方とかぐらいは回答できても、機能そのものについて
動かないとか報告されてもしょうがない気も・・・。
使ったことがある人がいたら、回答つくかもしれませんけどね。
???さんの挙げられたページのよくある質問を見てみるとCreateからResetしてますね。fxPAPI_Getは必要ない気がします。
まずC言語なりVBなりのサンプルを実行してクリアされるか確かめてみてはどうでしょうか。
あと、サンプルの記述など情報は初めに出せるだけ出しておくほうが良いですよ。
skさん、???さんありがとうございます。
>まずC言語なりVBなりのサンプルを実行してクリアされるか確かめてみては
>どうでしょうか。
はい、一度VBのサンプルを動かして確認してみます。
>あと、サンプルの記述など情報は初めに出せるだけ出しておくほうが良いで>すよ。
はい。
皆さんから頂戴した意見を元に再度色々チャレンジしてみます。
(メーカーへの問合せも含め)
お力頂きました皆様に感謝いたします。
改めて結果ご報告ならびにご質問させて頂きますのでよろしくお願いします。
PSLAD2を使った事が有りますので参考までに。
//定義
Function fxPAPI_Create(hWnd : Integer; lpDevice : String; iDBSwitch : Integer) : Integer; StdCall external 'PSLAD32.dll';
Function fxPAPI_Reset(hAPI : Integer; pInBuf : String) : Boolean; StdCall external 'PSLAD32.dll';
//実行
hAPI := fxPAPI_Create(0, 'FX DocuCentre C0000 FAX', SHOW_MESSAGEBOX_SERIOUS + SHOW_MESSAGEBOX_WARNING); //初期化
//fxPAPI_SetEXでの設定のクリアであって機械内部情報のクリアではないのでは?
isDone := fxPAPI_Reset(hAPI, 'FAXToNum');
//fxPAPI_SetEXでの設定
.
.
.
と設定します。
ツイート | ![]() |