掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
プリンタの使用可能な用紙名のリストを取得するには? (ID:44847)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
またMr.XRAYさんのサンプルの不具合かー …というのはウソです。 まず、ここをよく見てください。元々、要素数が1個しかありません。 > TPaperNames = array [0..0] of TPaperName; > TPaperNumber = array [0..0] of WORD; その一方、ビンの数はほぼ必ず2つ以上あるでしょうし、実際このユニット全体もビンの数が複数 あることを想定した作りになっています。 つまり、pPNames^[i] と pPNumber^[i] の i は宣言された要素の範囲 0..0 を超えるであろう、 ということが暗黙の前提となった上でコーディングされているのです。 その目的は、不定な(動的に可変する)アイテム数(ビンの数)への対応です。 この手法はかなり頻繁に使われています。C言語やClassicなDelphi(D3以前かな?)でも使える、 言わば 「ジェネリックな」テクニック …らしいです。 または、WindowsのAPIがキチ(ピ〜)なため、嫌でも使わざるを得ない局面もあると思います。 >実行時エラーが発生しないようにするには、どうしたらよいでしょうか? もうお分かりだと思いますが、ここは「範囲チェック」をOFFにしておく、というのが正解です。 …などという知ったかぶりの説明では、かんとくさんが納得しないと思うので、回避策を挙げてみます。 1. [0..0] ではなく、[0..65535] とかにして、範囲チェックに引っかからないようにする。 (ただし、よりインチキ臭くなる。)※具体的なコードは割愛。 2. あらかじめ、必要以上と思われる大量の配列を実際に確保し、使用する。 (ただし、メモリの無駄遣い。)※具体的なコードは割愛。 3. 動的配列を使い、必要な分だけ配列を確保する。(今回の局面では楽に適用可能。) ※下記の変更で try〜finally〜end; も無意味になっているので、除去すべきです。 procedure TForm1.ComboBox1CloseUp(Sender: TObject); type //用紙名リスト用.用紙名の文字数の最大は64 TPaperName = array [0..63] of Char; // TPaperNames = array [0..0] of TPaperName; // TPaperNumber = array [0..0] of WORD; // pPaperNames = ^TPaperNames; // pPaperNumber = ^TPaperNumber; var i,j : Integer; ADevice : array[0..MAX_PATH-1] of Char; ADriver : array[0..MAX_PATH-1] of Char; APort : array[0..MAX_PATH-1] of Char; ADeviceMode : THandle; Count : Integer; // pPNames : pPaperNames; // pPNumber : pPaperNumber; aPNames : array of TPaperName; aPNumber : array of WORD; AIndex : Integer; begin if ComboBox1.ItemIndex<0 then exit; //選択したプリンタを現在のプリンタとする Printer.PrinterIndex := ComboBox1.ItemIndex; //現在のプリンタに関する情報を取り出す Printer.GetPrinter(ADevice,ADriver,APort,ADeviceMode); //APortに接続しているプリンタADeviceのビンの数を取得 Count := DeviceCapabilities(ADevice,APort,DC_PAPERNAMES,nil,nil); //その数分だけビン名称とビン番号の配列用メモリを確保 // GetMem(pPNames,Count*SizeOf(TPaperName)); // GetMem(pPNumber,Count*SizeOf(TPaperNumber)); SetLength(aPNames, Count); SetLength(aPNumber, Count); //StringGridの行数 SGrid1.RowCount := Count+1; //表示開始時は1行目を選択 SGrid1.Row := 1; try //確保したメモリに用紙名と用紙番号がある // DeviceCapabilities(ADevice,APort,DC_PAPERNAMES,PChar(pPNames),nil); // DeviceCapabilities(ADevice,APort,DC_PAPERS,PChar(pPNumber),nil); DeviceCapabilities(ADevice,APort,DC_PAPERNAMES,PChar(aPNames)),nil); DeviceCapabilities(ADevice,APort,DC_PAPERS,PChar(aPNumber),nil); //StringGridに用紙名等を表示 if Count<1 then begin SGrid1.RowCount := 2; SGrid1.Cells[0,1] := '-'; SGrid1.Cells[1,1] := '-'; SGrid1.Cells[2,1] := ''; end else begin for i:=0 to Count-1 do begin // SGrid1.Cells[0,i+1] := String(pPNames^[i]); SGrid1.Cells[0,i+1] := String(aPNames[i]); //用紙番号 // AIndex := Integer(pPNumber^[i]); AIndex := Integer(aPNumber[i]); //用紙番号に相当する定数を検索 for j:=0 to PaperList.Count-1 do begin if AIndex=Integer(PaperList.Objects[j]) then begin SGrid1.Cells[1,i+1] := PaperList[j]; break; end; end; // SGrid1.Cells[2,i+1] := IntToStr(pPNumber^[i]); SGrid1.Cells[2,i+1] := IntToStr(aPNumber[i]); end; end; finally // FreeMem(pPNames); // FreeMem(pPNumber); end; end; こんな感じでよろしいですかね? 添削お願いします。>Mr.XRAYさん
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.