1.  $(lib)/win32/api/DeviceCaps.rb

1. ユースケース

1.1. 引数で受取ったCanvasがプリンタ用かどうかを調べる。。


----
nifty:FDELPHI/MES/06/30916

----
30916/30918 JCG00336  Satobe           RE:canvas の持ち主を調べる？
( 6)   00/04/06 01:58  30890へのコメント  コメント数：2

  キャド さん、こんにちは。Satobe です。

>のように書いて、画面表示時は、wr_graph( image1.canvas)
>印刷時は、wr_graph( printer.canvas) と順調に動作しています。

  Printer.Canvasかどうか？を判定したいのであれば、

  if Canvas = Printer.Canvas
    then //Printerである
    else //Printerでない

  これだけで済んでしまいそうな気がするのですが...

  APIでまっとうに調べるならば、

  if GetDeviceCaps(Canvas.Handle, TECHNOLOGY) = DT_RASPRINTER
    then //Printerである
    else //Printerでない

  こんな手もありますけど。
                                 00/04/06(木) 01:51 Satobe(JCG00336)
----


1.1. スクリーンの色の能力にあわせてプログラムをしたいとき



----
nifty:FDELPHI/MES/06/20505
----
20505/20543 KFA02326  ありい           RE:TabSheetの印刷について
( 6)   98/08/20 16:19  20504へのコメント  コメント数：1

　人間四季宝さん、こんにちは。

＞Form を印刷する場合，Printをつかうと印刷できますが，
＞Form にPageControlを貼付けてあって，PageControlの各Tabsheetを印刷したい
＞のですが，やり方がわかりません。
＞どのようにすればよいのでしょうか。

　Forms.pasのPrintの所からパクって来ました(笑)

　Formを指定している所を（PrintScaleの部分以外を）TabSheetを指定するよ
うに書き直しました。

　長いですが。

function GetSheetImage(Sheet: TTabSheet): TBitmap;
var
  ScreenDC, PrintDC: HDC;
  OldBits, PrintBits: HBITMAP;
  PaintLParam: Longint;

  procedure PrintHandle(Handle: HWND);
  var
    R: TRect;
    Child: HWND;
    SavedIndex: Integer;
  begin
    SavedIndex := SaveDC(PrintDC);
    Windows.GetClientRect(Handle, R);
    MapWindowPoints(Handle, Sheet.Handle, R, 2);
    with R do
    begin
      SetWindowOrgEx(PrintDC, -Left, -Top, nil);
      IntersectClipRect(PrintDC, 0, 0, Right - Left, Bottom - Top);
    end;
    SendMessage(Handle, WM_ERASEBKGND, PrintDC, 0);
    SendMessage(Handle, WM_PAINT, PrintDC, PaintLParam);
    Child := GetWindow(Handle, GW_CHILD);
    if Child <> 0 then
    begin
      Child := GetWindow(Child, GW_HWNDLAST);
      while Child <> 0 do
      begin
        PrintHandle(Child);
        Child := GetWindow(Child, GW_HWNDPREV);
      end;
    end;
    RestoreDC(PrintDC, SavedIndex);
  end;

begin
  Result := nil;
  ScreenDC := GetDC(Sheet.Handle);
  PaintLParam := 0;
  try
    PrintDC := CreateCompatibleDC(ScreenDC);
    try
      PrintBits := CreateCompatibleBitmap
        (ScreenDC, Sheet.ClientWidth, Sheet.ClientHeight);
      try
        OldBits := SelectObject(PrintDC, PrintBits);
        try
          { Clear the contents of the bitmap }
          FillRect(PrintDC, Sheet.ClientRect, Sheet.Brush.Handle);

          { Paint form into a bitmap }
          PrintHandle(Sheet.Handle);
        finally
          SelectObject(PrintDC, OldBits);
        end;
        Result := TBitmap.Create;
        Result.Handle := PrintBits;
        PrintBits := 0;
      except
        Result.Free;
        if PrintBits <> 0 then DeleteObject(PrintBits);
        raise;
      end;
    finally
      DeleteDC(PrintDC);
    end;
  finally
    ReleaseDC(Sheet.Handle, ScreenDC);
  end;
end;

procedure SheetPrint(Sheet: TTabSheet; Form: TForm);
var
  i: integer;

  FormImage: TBitmap;
  Info: PBitmapInfo;
  InfoSize: Integer;
  Image: Pointer;
  ImageSize: DWORD;
  Bits: HBITMAP;
  DIBWidth, DIBHeight: Longint;
  PrintWidth, PrintHeight: Longint;
begin
  Printer.BeginDoc;
  try
    FormImage := GetSheetImage(Sheet);
    try
      { Paint bitmap to the printer }
      // with Printer , Canvas do
      begin
        Bits := FormImage.Handle;
        GetDIBSizes(Bits, InfoSize, ImageSize);
        Info := AllocMem(InfoSize);
        try
          Image := AllocMem(ImageSize);
          try
            GetDIB(Bits, 0, Info^, Image^);
            with Info^.bmiHeader do
            begin
              DIBWidth := biWidth;
              DIBHeight := biHeight;
            end;
            case Form.PrintScale of
              poProportional:
                begin
                  PrintWidth := MulDiv(DIBWidth, GetDeviceCaps
                    (Printer.Handle, LOGPIXELSX), Form.PixelsPerInch);
                  PrintHeight := MulDiv(DIBHeight, GetDeviceCaps
                    (Printer.Handle, LOGPIXELSY), Form.PixelsPerInch);
                end;
              poPrintToFit:
                begin
                  PrintWidth := MulDiv
                    (DIBWidth, Printer.PageHeight, DIBHeight);
                  if PrintWidth < Printer.PageWidth then
                    PrintHeight := Printer.PageHeight
                  else
                  begin
                    PrintWidth := Printer.PageWidth;
                    PrintHeight := MulDiv
                      (DIBHeight, Printer.PageWidth, DIBWidth);
                  end;
                end;
            else
              PrintWidth := DIBWidth;
              PrintHeight := DIBHeight;
            end;
            StretchDIBits(Printer.Canvas.Handle, 0, 0,
              PrintWidth, PrintHeight, 0, 0, DIBWidth, DIBHeight,
              Image, Info^, DIB_RGB_COLORS, SRCCOPY);

          finally
            FreeMem(Image, ImageSize);
          end;
        finally
          FreeMem(Info, InfoSize);
        end;
      end;
    finally
      FormImage.Free;
    end;
  finally
    Printer.EndDoc;
  end;
end;

　上記のコードを下のコードよりも上に書きまして、

procedure TForm1.Button1Click(Sender: TObject);
begin
  SheetPrint(PageControl1.ActivePage, Form1);
end;

　とすれば、出てくると思います。PrintScaleはFormの値を参照します（する
はずです(^^;）

　もっと他に良い方法があるかもしれませんが、一応参考の為(^^)

　　　　　　　　　　　　　　　　　　　　ＫＦＡ０２３２６　ありい
----

----
nifty:FDELPHI/MES/06/16799
----
16799/16800 LEH06505  谷内　正彦　　　 RE:画面のプロパティがとりたい
( 6)   98/03/13 11:03  16796へのコメント

TETU さん、こんにちは。谷内と申します。

>プログラム中で画面のプロパティを取りたい（VGA設定か、色設定は２５６色か
>など）のですが、これはＡＰＩを使用しないと駄目でしょうか？
>もし、そうであればどういう命令ですか？

解像度は Screen.Width, Screen.Height で解ります。
TScreen でヘルプを参照してください。

色数は ＡＰＩ使用ですかね？
こんな感じです。

var
  DC: HDC;
  Colors: Integer;
  HRes, VRes: Integer;
begin
  DC := GetDC( 0 );

  // 色数 SIZEPALETTE は違うかも。
  Colors := GetDeviceCaps( DC, SIZEPALETTE ); // Win32API ヘルプ参照

  // 解像度を API でやるとこんな感じ
  HRes := GetDeviceCaps( DC, HORZRES ); // ディスプレイの幅
  VRes := GetDeviceCaps( DC, VERTRES ); // ディスプレイの高さ

  ReleaseDC( 0, DC );
end;

                                     98/03/13(金) 11:04 谷内　正彦(LEH06505)

----

1.1. プリンタの印字可能領域を調べる

----
nifty:FDELPHI/MES/11/5981
----
05981/05981 CXD02261  一品斎           RE:余白の編集の動的変更
(11)   99/04/28 18:55  05971へのコメント

あきお さん、こんにちは。一品斎です。(NIFTY:FDELPHI/MES/11/5971)

>のですが、余白の編集（プリンタドライバのプロパティの）については変更で
>きないのでしょうか？全部0に設定したいのです。

プリンタプロパティでの変更は知りませんが、余白を計算してそれに対応して
出力することはできます。

 var
   poffset,ppsize:TPoint;

で、

 poffset.x:=getdevicecaps(printer.handle,PHYSICALOFFSETX);
 poffset.y:=getdevicecaps(printer.handle,PHYSICALOFFSETY);
 ppsize.x:=getdevicecaps(printer.handle,PHYSICALWIDTH);
 ppsize.y:=getdevicecaps(printer.handle,PHYSICALHEIGHT);

として求めます。単位はピクセルです。


 +--------+-----------------+----------+
 +-------------------------------------+ ppsize.x　用紙の長さ
 +--------+                              poffset.x 余白の長さ
          +-----------------+  printer.pagewidth 印刷範囲の長さ

ということです。プリンタドライバによって誤差が出ますので、正確な印刷
はなかなか難しいようです。

ここで、printer.canvas.textout(0,0,'A'); とすると、左上に'A'が印字
されます。しかし、用紙の poffset.x 分右に印刷されます。これをもとに
計算するというのはどうでしょうか。

プリンタによっては、余白はまちまちですので、それぞれ計算して
求めることになるでしょう。

----------------------------------------------------------------------
1999.04.28(水)                                        一品斎  CXD02261
======================================================================

----

1.1. プリンタの解像度を調べて、mm単位で印刷物の大きさを指定したいとき。

----
nifty:FDELPHI/MES/10/7236
----
07236/07237 KYY06770  エックス         RE:PrevXで定型用紙への印字
(10)   00/07/05 02:46  07233へのコメント

大日　美智雄 さん こんにちは。

>PrevXを今ごろになって発見し大喜びしています。
>QuickReportでは難しい定型用紙への印刷に思い悩んでいたところ
>PrevXを発見し、使ってみるとわずか一日でできてしまいました。
>中略
>用紙の上左位置からの絶対位置に印字したいのですがどのようにすれば
>可能でしょうか。

　内部で使用している OffsetX 等には係数がかかっているようなので、直接
取得してもらいますか。
　たとえば GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX) などです。
　あと FMapMode が PmmLo のときに 値を 1/10 する必要はないと思います。

　ただ、この方法の場合 計算結果がマイナスになると問題になりますので、
以下のような方法がよさそうです。

function TPrevX.XPos(const x: Integer): Integer;
var
  Margin : Integer;
begin
  if FMapMode = pmmHi then begin
    Margin := Round((FMarginLeft * InchPixelsX) / 254) -
              GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
    if Margin < 0 then Margin := 0;
    Result := Round((x  * InchPixelsX) / 254) + Margin;
  end
  else begin
    Margin := Round((FMarginLeft * InchPixelsX) / 25.4) -
              GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
    if Margin < 0 then Margin := 0;
    Result := Round((x * InchPixelsX) / 25.4) + Margin;
  end;
end;

　そのうち時間が取れれば、もうちょっとまともにつくり直したいと思いま
す。それまではだましだまし使ってやってください。(^^;)

　ではでは～。

                            2000/07/05(Wed) 02:13am  KYY06770 エックス

----


----
nifty:FDELPHI/MES/06/26838
----
26838/26890 QZE10125  謎の全知師       RE:線の描画単位について
( 6)   99/06/25 11:27  26823へのコメント  コメント数：1

まさし さん、こんにちは。謎の全知師です。

>やりたい事はCADソフトのように小数点以下第三位までの数値で指定した
>線を引きたいのです。（単位は㎜です）

ディスプレイ上で0.001mmの精度を求めても意味が有りませんが、
一応下記の様にすれば簡単です。

まず、１インチ当たりのピクセル数を保持する変数をX,Yの分
用意します。で、初期処理などで、

  InchPerPixelX := GetDeviceCaps(Canvas.Handle, LOGPIXELSX);
  InchPerPixelY := GetDeviceCaps(Canvas.Handle, LOGPIXELSY);

次に、mmをPixelに変換する関数をX,Yの分用意します。

function mmToPixX(mm : Double) : Integer;
begin
  Result := Round(mm * (InchPerPixelX / 25.4));
 //  Result := Round(mm * (InchPerPixelX / 25.4) * ZoomFacter);
 //  このようにしておけば拡大/縮小も楽
end;

function mmToPixY(mm : Double) : Integer;
begin
  Result := Round(mm * (InchPerPixelY / 25.4));
end;

で、線を引く時に、

  Canvas.MoveTo(mmToPixX(10.54), mmToPixY(0.03));
  Canvas.LineTo(mmToPixX(20.0), mmToPixY(0.03));

ディスプレイ上ではX,Yの解像度は大抵同じですが、上記の
様にしておけば汎用的に使えます。

                                     99/06/25(金) 10:26 謎の全知師(QZE10125)

----


----
nifty:FDELPHI/MES/06/21212
----
21212/21215 CXG00064  kiima            RE:プリンタ用紙サイズの取得
( 6)   98/09/21 16:17  21209へのコメント  コメント数：1

ども、島村　幸一 さん こんにちは

>W := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
>H := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);

これって戻り値の単位はピクセルという仕様になってたはずです。
mm単位の値が欲しければ

xppi := GetDeviceCaps(Printer.Handle, LOGPIXELSX)
yppi := GetDeviceCaps(Printer.Handle, LOGPIXELSY)

で解像度を求めて

Wmm := W / xppi * 25.4
Hmm := H / yppi * 25.4

でＯＫじゃないかな？ (^_^)

                          /*** kiima | CXG00064@nifty.ne.jp ***/

----
nifty:FDELPHI/MES/06/21213
----
21213/21215 MAF01541  島村　幸一　　　 RE:プリンタ用紙サイズの取得
( 6)   98/09/21 16:34  21209へのコメント

自己レスです。

GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
で帰ってくる数値は Pixel なのですね。 mm とばかり思い込んでいました。
プリンタの解像度を考慮してあって、数字が似ていたのですっかり２倍に
なっていると思い込んでいました。お騒がせしました。

因に、プリンタの解像度が３６０ｄｐｉのとき、Ａ４の短辺は２１０ｍｍで
得られた数字：２９７７／３６０＊２５．４＝２１０　となりました。


----


----
nifty:FDELPHI/MES/06/16155
----
｜Printer.Canvas.Font.PixelsPerInchにLOGPIXELSXの値を
｜代入してから、計算を行って見てください。

ということで

Printer.Canvas.Font.PixelsPerInch:=
　GetDeviceCaps(printer.handle,LOGPIXELSX);

としたら、出来ました。ありがとうございます。
行数を求めるのでLOGPIXELSYかなとも思ったのですが、PixelsPerInchってのが、何
の値（高さor幅）をとるのかわかないので、しかも、概算の数値でもＯＫなので、
どっちでも大丈夫のようです。

helpで"PixelsPerInch"を調べたら「変更してはなりません。」と前近代的な言い回
し・・・。謎の全知師 さんにしてみれば、平気で弄れちゃうんだなぁと尊敬いたし
ました。
----

----
nifty:FDELPHI/MES/06/15107
----
15107/15192 CXD02261  一品斎           RE^3:プリンター用紙の取得
( 6)   98/01/16 22:24  15088へのコメント  コメント数：1

伊関 和弘 さん、こんにちは。一品斎です。(NIFTY:FDELPHI/MES/6/15088)

>紙の寸法は取得できないのでしょうか？

ヘルプを見て追加すると、

　dmy^.dmPaperwidth
　dmy^.dmPaperlength

というので取得できそうですね。

　round((getdevicecaps(printer.handle,PHYSICALWIDTH)*25.4)/
         getdevicecaps(printer.handle,LOGPIXELSX))
　round((getdevicecaps(printer.handle,PHYSICALHEIGHT)*25.4)/
         getdevicecaps(printer.handle,LOGPIXELSY))

とやっても取得できます。現在選択している用紙なら。

----------------------------------------------------------------------
1998.01.16(金)                                        一品斎  CXD02261
======================================================================

----

nifty:FDELPHI/MES/06/12099
----
12099/12136 KHB05271  瑠瓏             RE:プリンターの解像度と印刷の関係につい
( 6)   97/09/25 16:08  12092へのコメント  コメント数：1

紫苑 さん、どもです　瑠瓏です。

procedure TForm1.Button1Click(Sender: TObject);
  fumction mm(e:single):integer;
  var dx:integer;
  begin
    dx:=GetDeviceCaps(Printer.Handle,LOGPIXELSX);
    Result:=Trunc(e*dx/25.4)
  end;
begin
  with Printer,Printer.Canvas do begin
    BeginDoc;

    TextOut(mm(67.7),mm( 8.0),'皆さんよろしくお願いします');
    TextOut(mm(67.7),mm(14.0),'ご教授下さい');
    Pen.Width:=mm(0.3);
    Rectangle(mm(65.0),mm(7.0),mm(140.0),mm(23.0));

    EndDoc;
  end;
end;

>過去ログや本などを 色々見てみましたが、どうしたらよいか答えが
>見つかりません。

nifty:FDELPHI/MES/06/8031
nifty:FDELPHI/MES/06/8035
nifty:FDELPHI/MES/06/6288
などに、同様のが載ってます(^^a

長月。秋分、涼風の舞 FDELPHI ☆ 瑠瓏 <KHB05271@niftyserve.or.jp>
Count Down Six days for FJBuildr          97/9/25(Thu) 15:33
----

----
nifty:FDELPHI/MES/06/10326
----
いくつかの方法を試した結果、いまのところ次のような結論に達しています。
（あくまでも「いまのところ」です）

　　Printer.PageWidth, Printer.PageHeight に関しては、ダイアログで変更
　　後、直ちに値が修正され、修正された値をプログラムで取得することがで
　　きる。

　　GetPrinter(DrvName,PrtName, PortName, DeviceMode);
　　PdevMode := GlobalLock(DeviceMode); の方法は、何かのタイミングで値
　　が修正されるため、すぐに新しい設定値を取得することはできない。

　　GetDeviceCaps(Printer.Handle, PHYSICALWIDTH) の方法では、直ちに新し
　　い設定値を取得することができる。

と、いった次第です。DeviceMode のやり方がなぜうまくいかないのかは分かり
ませんが、いまのところ GetDeviceCaps のやり方で目的を達成できていますの
で、「これでよし」といった次第です。
----

----
nifty:FDELPHI/MES/06/10979
----
10979/10996 CXD02261  一品斎           RE^6:印刷についてＱ（長文ｿｰｽあり）
( 6)   97/08/25 20:13  10961へのコメント

ユニコムTM さん、こんにちは。一品斎です。（NIFTY:FDELPHI/MES/6/10961)

>  dpiの差異に対する対処がなされていない気がするのですが...

ずばり、その通りですね。(^^;)

プリ　さん、プロッターのdpi(dot per inch)と、プリンターのdpiが違うのが
原因です。

もし、図面などを縮尺をきちんと、印刷したいのなら、
　printer.canvas.textout(1000,1000,'a');
というような座標系をセンチかインチに直す必要があります。

一応、簡単に原理を説明いたしますね。(^^;)

　300dpiとは、１インチあたり300ドットあるわけです。
　600dpiとは、１インチあたり600ドットあるわけです。
　これは、getdevicecaps(printer.handle,LOGPIXELSY);　で取得できます。

　すると、1200ドット(ピクセル)は、300dpi->４インチ、600dpi->2インチ
となってしまいます。

　１インチは2.54センチです。50mmをピクセル（ドット）にするには、
　　　(50/25.4)*getdevicecaps(printer.handle,LOGPIXELSY);
　とします。

  あとは、function W()に数値を変更すれば、きちんと印刷できます。
  p_width をmmとして作成します。

　　function W(p_width:integer):integer;
          var  LOGY:integer
          begin
            LOGY:=getdevicecaps(printer.handle,LOGPIXELSY);
            if p_width=0 then result:=0
             else result:=round(p_width / 25.4 * LOGY);
            {ここは、try～endの方がきれいかもしれません。}
          end;

 こうして、textout(w(50),w(100),'A');　とすれば、印刷可能範囲の左上
から、右に50mm、左に100mmの所を左上とした文字「Ａ」が印刷できます。

多分これで、いいと思います。

もし、fontを指定するのでしたら、
printer.canvas.font.pixelsperinch:=getdevicecaps(printer.handle,LOGPIXELSY);
とした方が正確に印刷することができます。

プロッターや、プリンターによっては、縦と横のdpiが異なる場合があります
ので、LOGPIXELSX を取得して、計算する必要があるかもしれません。

これでどうでしょうか？　m(_._)m
----
nifty:FDELPHI/MES/06/11123
----
11123/11358 BZH17723  プリ             RE^4:印刷についてＱ（長文ｿｰｽあり）
( 6)   97/08/29 22:53  10946へのコメント  コメント数：1

一品斎  さんこん○○はプリです。

レス遅れてすみません（土日しかアクセスしてないもので）
ありがとうございました。

いちを、下記のようにしてみたら、うまく行ってるみたいです。

procedure TForm1.Print4Click(Sender: TObject);
 function W(p_width:integer):integer;
{ const proter_w=PW;{プロッターのprinter.pagewidthを仮に2400 とします}
     var
         Proter_W:integer;
         W_w:real;
    begin
 Proter_w:=GetDeviceCaps(Printer.Handle,HORZRES);
 W_w:=printer.pagewidth / proter_w;
 {W_h:=printer.pageheight / proter_h;   }
            if p_width=0 then result:=0
                         else result:=trunc(p_width * W_w);
       {ここは、try～endの方がきれいかもしれません。}
          end;

function H(p_height:integer):integer;
{const  proter_h=2000;{プロッターのprinter.pageheightを仮に1200 とします}
        var  W_h:real;
             Proter_H:Integer;
         begin
             Proter_h:=GetDeviceCaps(Printer.Handle,VERTRES);
             W_h:=printer.pageheight / proter_h;
          if p_height=0 then result:=0
                        else result:=trunc(p_height * W_h);
    {ここは、try～endの方がきれいかもしれません。}
         end;
 begin
   if  PrintDlg.Execute then begin
       Printer.BeginDoc;
  with Printer.Canvas do
   begin
    try
     Moveto(W(0),H(0));
     MoveTo(W(100),H(250));
     Lineto(W(100),H(1300));
     LineTo(W(2300),H(1300));
     MoveTo(W(100),H(250));
     LineTo(W(2300),H(250));
     LineTo(W(2300),H(1300));

てなぐわいです。
----

1. 参考

http://www.microsoft.com/japan/developer/library/jpgdipf/_win32_getdevicecaps.htm

GetDeviceCaps

指定されたデバイスに関するデバイス固有の情報を取得します。

int GetDeviceCaps(
  HDC hdc,     // デバイスコンテキストのハンドル
  int nIndex   // 能力のインデックス
);

パラメータ：

hdc		デバイスコンテキストのハンドルを指定します。
nIndex	取得対象の項目を指定します。次の値のいずれかを指定します。

インデックス		意味

DRIVERVERSION		デバイスドライバのバージョン。

TECHNOLOGY			デバイステクノロジ（タイプ）。次の値のいずれかが返ります。

	DT_PLOTTER			ベクタプロッタ
	DT_RASDISPLAY		ラスタディスプレイ
	DT_RASPRINTER		ラスタプリンタ
	DT_RASCAMERA		ラスタカメラ
	DT_CHARSTREAM		文字ストリーム
	DT_METAFILE			メタファイル
	DT_DISPFILE			ディスプレイファイル

hdc パラメータで拡張メタファイルのデバイスコンテキストのハンドルを指定した場合、CreateEnhMetaFile 関数を呼び出したときに指定した参照デバイスのデバイステクノロジが返ります。hdc パラメータで指定したオブジェクトが拡張メタファイルのデバイスコンテキストかどうかを調べるには、GetObjectType 関数を使います。

HORZSIZE		ミリメートル（mm）単位の画面の物理的な幅。
VERTSIZE		ミリメートル（mm）単位の画面の物理的な高さ。

HORZRES			ピクセル単位の画面の幅。
VERTRES			ピクセル単位（ラスタ行数）の画面の高さ。

LOGPIXELSX		画面の水平方向での、論理インチ当たりのピクセル数。マルチモニタを接続しているシステムでは、すべてのモニタでこの値が等しくなります。
LOGPIXELSY		画面の垂直方向での、論理インチ当たりのピクセル数。マルチモニタを接続しているシステムでは、すべてのモニタでこの値が等しくなります。

BITSPIXEL		ピクセルあたりのカラービットの数。

PLANES			カラープレーンの数。

NUMBRUSHES		デバイス固有のブラシの数。

NUMPENS			デバイス固有のペンの数。

NUMFONTS		デバイス固有のフォントの数。

NUMCOLORS		デバイスのカラー深度が 8bpp（ピクセル当たり 8 ビット）以下の場合は、デバイスのカラーテーブル内のエントリ数を取得します。色深度が 8bpp を超える場合、-1 が返ります。

ASPECTX		線の描画に使うデバイスピクセルの相対的な幅。

ASPECTY		線の描画に使うデバイスピクセルの相対的な高さ。

ASPECTXY		線の描画に使うデバイスピクセルの対角線の幅。

PDEVICESIZE		予約済み。

CLIPCAPS		デバイスのクリッピング能力を示すフラグ。デバイスが長方形のクリップをサポートする場合は 1、それ以外の場合は 0 です。

SIZEPALETTE		システムパレット内のエントリ数。デバイスドライバが、nIndex パラメータの RASTERCAPS インデックスで RC_PALETTE ビットをセットした場合にのみ、SIZEPALETTE インデックスは有効です。また、ドライバが 16 ビット版の Windows との互換性を備えている場合にのみ、利用できます。

NUMRESERVED		システムパレット内の予約エントリ数。デバイスドライバが、nIndex パラメータの RASTERCAPS インデックスで RC_PALETTE ビットをセットした場合にのみ、NUMRESEVED インデックスは有効です。また、ドライバが 16 ビット版の Windows との互換性を備えている場合にのみ、利用できます。

COLORRES		デバイスの実際の色深度を表す、ピクセル当たりのビット数。デバイスドライバが、nIndex パラメータの RASTERCAPS インデックスで RC_PALETTE ビットをセットした場合にのみ、COLORRES インデックスは有効です。また、ドライバが 16 ビット版の Windows との互換性を備えている場合にのみ、利用できます。

PHYSICALWIDTH		印刷デバイス用です。ページの物理的な幅をデバイス単位で表します。たとえば、8.5"×11" の用紙に 600dpi の解像度で印刷するよう設定されているプリンタでは、物理的な幅は 5,100 デバイス単位になります（8.5×600=5,100）。ほとんどの場合、用紙の印字可能領域は用紙の物理的な幅よりも多少小さいこと、そして印字可能領域は物理的な幅を決して上回らないことに注意してください。

PHYSICALHEIGHT		印刷デバイス用です。ページの物理的な高さをデバイス単位で表します。たとえば、8.5"×11" の用紙に 600dpi の解像度で印刷するよう設定されているプリンタでは、物理的な高さは 6,600 デバイス単位になります（11×600=6,600）。ほとんどの場合、用紙の印字可能領域は用紙の物理的な高さよりも多少小さいこと、そして印字可能領域は物理的な高さを決して上回らないことに注意してください。

PHYSICALOFFSETX		印刷デバイス用です。物理的なページの左端から印刷可能領域の左端までの距離をデバイス単位で表します。たとえば、8.5"×11" の用紙に 600dpi の解像度で印刷するよう設定されているプリンタで、用紙の左端 0.25 インチ（6.4mm）への印字が行えない場合、水平方向の物理オフセットは 150 デバイス単位になります（0.25×600=150）。

PHYSICALOFFSETY		印刷デバイス用です。物理的なページの上端から印刷可能領域の上端までの距離をデバイス単位で表します。たとえば、8.5"×11" の用紙に 600dpi の解像度で印刷するよう設定されているプリンタで、用紙の上端 0.5 インチ（12.7mm）への印字が行えない場合、水平方向の物理オフセットは 300 デバイス単位になります（0.5×600=300）。

VREFRESH		Windows NT/2000：ディスプレイデバイス用です。デバイスの現在のリフレッシュレート（垂直同期周波数）を 1 秒当たりのサイクル数（Hz）で表します。

	リフレッシュレートとして 0 または 1 が返された場合、現在の周波数は、ディスプレイハードウェアの既定のリフレッシュレートに等しいかどうかを意味します。通常、既定のレートを設定するには、グラフィックカードやマザーボードの DIP スイッチ、または ChangeDisplaySettings のような Win32 の表示関数を利用しない構成プログラムを使います。

SCALINGFACTORX		プリンタの水平軸の倍率。

SCALINGFACTORY		プリンタの垂直軸の倍率。

BLTALIGNMENT		Windows NT/2000：水平方向のアラインメント（整列単位）の優先値をピクセル単位で取得します。最大の描画パフォーマンスを得るには、各ウィンドウの水平位置をこの値の整数倍に整列させるべきです。値として 0 が返った場合、このデバイスが既にアクセラレート状態になっていて、任意のアラインメントを利用できることを意味します。

SHADEBLENDCAPS		Windows 98 と Windows 2000：デバイスのシェーディング（陰影）とブレンディング（混色）の能力を示す値です。

	SB_CONST_ALPHA		このデバイスは、BLENDFUNCTION 構造体の SourceConstantAlpha メンバを操作できます。この構造体は、AlphaBlend 関数の blendFunction パラメータで参照したものです。
	SB_GRAD_RECT		このデバイスには、GradientFill 関数を使って長方形を処理する能力があります。
	SB_GRAD_TRI			このデバイスには、GradientFill 関数を使って三角形を処理する能力があります。
	SB_NONE				このデバイスはこれらの能力をサポートしていません。
	SB_PIXEL_ALPHA		このデバイスには、AlphaBlend 関数を使って、ピクセルごとのアルファ（透明度、輝度）を操作する能力があります。
	SB_PREMULT_ALPHA	このデバイスには、AlphaBlend 関数を使って、あらかじめ倍率を設定されたアルファを操作する能力があります。

RASTERCAPS		デバイスのラスタ能力を示します。次の値の組み合わせになります。

	RC_BANDING		バンド処理のサポートが必要です。バンド処理とは、1 つのページを複数のセクション（バンド）へ分割する手法のことで、処理時間は多少長くなりますが、1 つのページを作成するために必要なメモリを削減できます。
	RC_BITBLT		このデバイスには、ビットマップの転送能力があります。
	RC_BITMAP64		このデバイスは、64 キロバイト（KB）より大きいビットマップをサポートしています。
	RC_DI_BITMAP	このデバイスは、SetDIBits 関数と GetDIBits 関数をサポートしています。
	RC_DIBTODEV		このデバイスは、SetDIBitsToDevice 関数をサポートしています。
	RC_FLOODFILL	このデバイスには、塗りつぶしを行う能力があります。
	RC_GDI20_OUTPUT	このデバイスは、16 ビット版の Windows 2.0 の機能をサポートしています。
	RC_PALETTE		このデバイスは、パレットベースのデバイスとして指定できます。
	RC_SCALING		このデバイスには、スケーリングを行う能力があります。
	RC_STRETCHBLT	このデバイスには、StretchBlt 関数を実行する能力があります。
	RC_STRETCHDIB	このデバイスには、StretchDIBits 関数を実行する能力があります。

CURVECAPS		デバイスの曲線描画能力を示します。次の値の組み合わせになります。

	CC_NONE				このデバイスは、曲線をサポートしていません。
	CC_CHORD			このデバイスは、弓形（弧と弦からなる図形）の弧を描画できます。
	CC_CIRCLES			このデバイスは、円を描画できます。
	CC_ELLIPSES			このデバイスは、楕円を描画できます。
	CC_INTERIORS		このデバイスは、内部の塗りつぶしを行えます。
	CC_PIE				このデバイスは、扇形を描画できます。
	CC_ROUNDRECT		このデバイスは、角の丸い長方形を描画できます。
	CC_STYLED			このデバイスは、スタイル付きの境界線を描画できます。
	CC_WIDE				このデバイスは、太い境界線を描画できます。
	CC_WIDESTYLED		このデバイスは、スタイル付きの太い境界線を描画できます。

LINECAPS		デバイスの直線描画能力を示します。次の値の組み合わせになります。

	LC_NONE		このデバイスは、直線をサポートしていません。

	LC_INTERIORS		このデバイスは、内部の塗りつぶしを行えます。

	LC_MARKER		このデバイスは、1 個のマーカーを描画できます。

	LC_POLYLINE		このデバイスは、連続直線を描画できます。

	LC_POLYMARKER		このデバイスは、複数のマーカーを描画できます。

	LC_STYLED		このデバイスは、スタイル付きの直線を描画できます。

	LC_WIDE		このデバイスは、太い直線を描画できます。

	LC_WIDESTYLED		このデバイスは、スタイル付きの太い直線を描画できます。

POLYGONALCAPS		デバイスの多角形描画能力を示します。次の値の組み合わせになります。

	PC_NONE		このデバイスは、多角形をサポートしていません。

	PC_INTERIORS		このデバイスは、内部の描画を行えます。

	PC_POLYGON		このデバイスは、交互モードの塗りつぶしを行えます。詳細については、SetPolyFillMode の解説を参照してください。

	PC_RECTANGLE		このデバイスは、長方形を描画できます。

	PC_SCANLINE		このデバイスは、単一の走査行を描画できます。

	PC_STYLED		このデバイスは、スタイル付きの境界線を描画できます。

	PC_WIDE		このデバイスは、太い境界線を描画できます。

	PC_WIDESTYLED		このデバイスは、スタイル付きの太い境界線を描画できます。

	PC_WINDPOLYGON		このデバイスは、全域モードでの多角形の塗りつぶしを行えます。詳細については、SetPolyFillMode の解説を参照してください。

TEXTCAPS		デバイスのテキスト表示能力を示します。次の値の組み合わせになります。

	TC_OP_CHARACTER		このデバイスには、キャラクタの出力精度を調整する能力があります。

	TC_OP_STROKE		このデバイスには、ストロークの出力精度を調整する能力があります。

	TC_CP_STROKE		このデバイスには、ストローククリップの精度を調整する能力があります。

	TC_CR_90		このデバイスには、キャラクタの 90 度回転を行う能力があります。

	TC_CR_ANY		このデバイスには、キャラクタの任意の角度の回転を行う能力があります。

	TC_SF_X_YINDEP		このデバイスは、x 方向と y 方向の独立したスケーリング（長体と平体）を行えます。

	TC_SA_DOUBLE		このデバイスは、キャラクタの 2 倍のスケーリング（倍角）を行えます。

	TC_SA_INTEGER		このデバイスは、キャラクタの整数倍のスケーリング（n 倍角）を行えます。

	TC_SA_CONTIN		このデバイスは、キャラクタの任意の倍率のスケーリングを行えます。

	TC_EA_DOUBLE		このデバイスは、2 倍の太さの文字（太字）を描画できます。

	TC_IA_ABLE		このデバイスは、イタリック体を描画できます。

	TC_UA_ABLE		このデバイスは、下線を描画できます。

	TC_SO_ABLE		このデバイスは、取り消し線を描画できます。

	TC_RA_ABLE		このデバイスは、ラスタフォントを描画できます。

	TC_VA_ABLE		このデバイスは、ベクトルフォントを描画できます。

	TC_RESERVED		予約済みです。このフラグは必ず 0 になります。

	TC_SCROLLBLT		このデバイスは、ビットブロック転送（ブリット）によるスクロールを行えません。このフラグが、予期とは逆のことを意味する可能性があることに注意してください。

COLORMGMTCAPS		Windows 2000：デバイスの色の管理（カラーマネジメント）能力を示します。

CM_CMYK_COLOR		このデバイスは、CMYK（シアン、マゼンタ、イエロー、ブラック）のカラースペース（色空間）に基づく ICC（International Color Consortium）のカラープロファイルを受け入れます。

CM_DEVICE_ICM		このデバイスは、デバイスドライバまたはデバイスの側で ICM（イメージ色の管理）を実施できます。

CM_GAMMA_RAMP		このデバイスは、GetDeviceGammaRamp と SetDeviceGammaRamp の各関数をサポートしています。

CM_NONE		このデバイスは、ICM をサポートしていません。

戻り値

要求した項目に対応する値が返ります。

nIndex パラメータで BITSPIXEL を指定し、デバイスの色深度が 15bpp または 16bpp の場合、16 が返ります。

解説

GetDeviceCaps は、プリンタエスケープの代わりに、次の 6 種類のインデックスを提供しています。

インデックス		置き換えられたプリンタエスケープ

PHYSICALWIDTH		GETPHYSPAGESIZE

PHYSICALHEIGHT		GETPHYSPAGESIZE

PHYSICALOFFSETX		GETPRINTINGOFFSET

PHYSICALOFFSETY		GETPHYSICALOFFSET

SCALINGFACTORX		GETSCALINGFACTOR

SCALINGFACTORY		GETSCALINGFACTOR

対応情報

Windows NT/2000：Windows NT 3.1 以降

Windows 95/98：Windows 95 以降
ヘッダー：Wingdi.h 内で宣言、Windows.h をインクルード
インポートライブラリ：Gdi32.lib を使用

参照

CreateEnhMetaFile, CreateIC, DeviceCapabilities, GetDIBits, GetObjectType, SetDIBits, SetDIBitsToDevice, StretchBlt, StretchDIBits

c2001 Microsoft Corporation. All rights reserved. Terms of Use

----

http://www.borland.co.jp/qanda/delphi/d0009388.html

 Borland Delphi

実行環境の画面設定が最大何色まで発色できるかを知るには(99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

実行環境の画面設定が最大何色まで発色できるかを知るにはどうしたらいいですか？

Windows API の GetDeviceCaps()を使って, １ピクセルを表現するために必要なビット数が以下の式で求められます。

   GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) *
   GetDeviceCaps(Form1.Canvas.Handle, PLANES)

最大発色数は「１ピクセルを表現するために必要なビット数」を調べることで知る
ことができます。

ビット数と最大発色数の関係

	1	=	2 色
	4	=	16 色
	8	=	256 色
	15	=	32768 色 (多くのドライバは 16 を返す)
	16	=	65535 色
	24	=	16,777,216 色
	32	=	16,777,216 色 (24bit と同じ)

最大表示色は以下の式で求められます。

   NumberOfColors := (1 shl
     (GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) *
      GetDeviceCaps(Form1.Canvas.Handle, PLANES));

----

http://www.borland.co.jp/tips/delphi/dh008/

……

（Screen::）PixelsPerInch は、1インチあたりのピクセル数を保持している読み込み専用プロパティです。この値は、フォームの PixelsPerInch に適用され、フォームの相対的な大きさを決定します。このプロパティを用いて、ビデオ画面の大きさを判断するのは適当ではありません。もし、もっと詳細な画面デバイス情報を取得したいならば、Windows API を用います。

GetDeviceCaps は、デバイスの能力を問い合わせる API 関数です。画面デバイスの表示能力を取得するには、画面デバイスを出力先とするキャンバスのハンドル（例えば、フォームの Canvas.Handle プロパティ）を引数として、この関数を呼び出します。

   with Memo1.Lines do begin
     Add(Format('物理画面の幅 = %d mm',
       [GetDeviceCaps(Canvas.Handle, HORZSIZE)]));
     Add(Format('物理画面の高さ = %d mm',
       [GetDeviceCaps(Canvas.Handle, VERTSIZE)]));
     Add(Format('ディスプレイの幅 = %d pixels',
       [GetDeviceCaps(Canvas.Handle, HORZRES)]));
     Add(Format('ディスプレイの高さ = %d pixels',
       [GetDeviceCaps(Canvas.Handle, VERTRES)]));
     Add(Format('各ピクセルのビットの数 = %d',
       [GetDeviceCaps(Canvas.Handle, BITSPIXEL)]));
    end;

……

----

http://yokohama.cool.ne.jp/chokuto/hsp/api/GetDeviceCaps.html

GetDeviceCaps

指定されたデバイスに関するデバイス固有の情報を取得します。

int GetDeviceCaps(
    HDC  hDC,     //デバイスコンテキストのハンドル
    int  nIndex   //項目の種類
);

使用DLL：GDI32.DLL

引数

hDC		デバイスコンテキストのハンドルを指定します。
nIndex		取得する情報の種類を指定します。以下の値のいずれかを指定します。

値					意味

0 (DRIVERVERSION)	デバイスドライバのバージョン
2 (TECHNOLOGY)		デバイステクノロジー。以下の値のいずれかが返ります。

	値						意味
	0 (DT_PLOTTER)			ベクタプロッタ
	1 (DT_RASDISPLAY)		ラスタディスプレイ
	2 (DT_RASPRINTER)		ラスタプリンタ
	3 (DT_RASCAMERA)		ラスタカメラ
	4 (DT_CHARSTREAM)		文字ストリーム
	5 (DT_METAFILE)			メタファイル
	6 (DT_DISPFILE)			ディスプレイファイル

4 (HORZSIZE)
6 (VERTSIZE)		物理画面の幅・高さ（ミリメートル単位）

8 (HORZRES)
10 (VERTRES)		画面の幅・高さ（ピクセル単位）

12 (BITSPIXEL)		ピクセルあたりのカラービットの数 (プレーンごと)

14 (PLANES)			カラープレーンの数

16 (NUMBRUSHES)		デバイス固有のブラシの数

18 (NUMPENS)		デバイス固有のペンの数

20 (NUMMARKERS)		デバイス固有のマーカーの数

22 (NUMFONTS)		デバイス固有のフォントの数

24 (NUMCOLORS)		デバイスのカラーテーブルのエントリ数 (ピクセルあたり 8 ビットを超える場合は -1)

28 (CURVECAPS)		デバイスの曲線描画能力。戻り値として次の値の組み合わせの値が返ります。

	値						サポートする曲線
	0 (CC_NONE)				曲線をサポートしない
	1 (CC_CIRCLES)			円
	2 (CC_PIE)				扇形
	4 (CC_CHORD)			弓形
	8 (CC_ELLIPSES)			楕円
	16 (CC_WIDE)			太い線
	32 (CC_STYLED)			スタイル付きの線
	64 (CC_WIDESTYLED)		スタイル付きの太い線
	128 (CC_INTERIORS)		内部の塗りつぶしをサポート
	256 (CC_ROUNDRECT)		角の丸い長方形

30 (LINECAPS)		デバイスの直線描画能力。戻り値として次の値の組み合わせの値が返ります。

	値					サポートする直線
	0 (LC_NONE)			直線をサポートしない
	2 (LC_POLYLINE)		折れ線
	4 (LC_MARKER)		マーカー
	8 (LC_POLYMARKER)	ポリマーカー
	16 (LC_WIDE)		太い直線
	32 (LC_STYLED)		スタイル付きの直線
	64 (LC_WIDESTYLED)	スタイルを持つ太い直線
	128 (LC_INTERIORS)	内部の塗りつぶしをサポート

32 (POLYGONALCAPS)		デバイスの多角形描画能力。戻り値として次の値の組み合わせの値が返ります。

	値									サポートする多角形
	0 (PC_NONE)							多角形をサポートしない
	1 (PC_POLYGON)						交互モードの塗りつぶし
	2 (PC_RECTANGLE)					長方形
	4 (PC_WINDPOLYGON, PC_TRAPEZOID)	全域モードでの塗りつぶし
	8 (PC_SCANLINE)						単一の走査行の描画
	16 (PC_WIDE)						太い線
	32 (PC_STYLED)						スタイル付きの線
	64 (PC_WIDESTYLED)					スタイル付きの太い線
	128 (PC_INTERIORS)					内部の塗りつぶしをサポート
	256 (PC_POLYPOLYGON)				ポリポリゴン
	512 (PC_PATHS)						パス

34 (TEXTCAPS)		デバイスのテキスト表示能力。戻り値として次の値の組み合わせの値が返ります。

	値								サポートするテキスト表示
	0x00000001 (TC_OP_CHARACTER)	キャラクタの出力精度
	0x00000002 (TC_OP_STROKE)		ストロークの出力精度
	0x00000004 (TC_CP_STROKE)		ストローククリップの精度
	0x00000008 (TC_CR_90)			キャラクタの 90 度回転
	0x00000010 (TC_CR_ANY)			キャラクタの任意の角度の回転
	0x00000020 (TC_SF_X_YINDEP)		x 方向と y 方向の両方の独立したスケー リング
	0x00000040 (TC_SA_DOUBLE)		キャラクタの 2 倍のスケーリング
	0x00000080 (TC_SA_INTEGER)		キャラクタの整数倍のスケーリング
	0x00000100 (TC_SA_CONTIN)		キャラクタの任意の倍率のスケーリング
	0x00000200 (TC_EA_DOUBLE)		太字
	0x00000400 (TC_IA_ABLE)			イタリック体
	0x00000800 (TC_UA_ABLE)			下線
	0x00001000 (TC_SO_ABLE)			取り消し線
	0x00002000 (TC_RA_ABLE)			ラスタフォント
	0x00004000 (TC_VA_ABLE)			ベクトルフォント
	0x00008000 (TC_RESERVED)		予約済み
	0x00010000 (TC_SCROLLBLT)		ビットブロック転送によるスクロールをサ ポートしない

36 (CLIPCAPS)		デバイスのクリッピング能力。戻り値として、長方形のクリップをサポートする場合は 1 が、それ以外の場合は 0 が返ります。

38 (RASTERCAPS)		デバイスのラスタ能力。戻り値として次の値の組み合わせの値が返ります。

	値							サポートする機能
	1 (RC_BITBLT)				ビットマップの転送
	2 (RC_BANDING)				バンド処理のサポートが必要
	4 (RC_SCALING)				スケーリング
	8 (RC_BITMAP64)				64KB より大きいビットマップ
	0x0010 (RC_GDI20_OUTPUT)	Windows2.0 の機能
	0x0080 (RC_DI_BITMAP)		SetDIBits 関数と GetDIBits 関数
	0x0100 (RC_PALETTE)			デバイスはパレットベースのデバイスである
	0x0200 (RC_DIBTODEV)		SetDIBitsToDevice 関数
	0x0800 (RC_STRETCHBLT)		StretchBlt 関数
	0x1000 (RC_FLOODFILL)		塗りつぶし
	0x2000 (RC_STRETCHDIB)		StretchDIBits 関数

40 (ASPECTX)
42 (ASPECTY)			線の描画に使うデバイスピクセルの相対幅・高さ
44 (ASPECTXY)			線の描画に使うデバイスピクセルの対角線の長さ

88 (LOGPIXELSX)
90 (LOGPIXELSY)			論理インチ当たりの画面の水平方向・垂直方向のピクセル数

104 (SIZEPALETTE)		システムパレット内のエントリ数

106 (NUMRESERVED)		システムパレット内の予約エントリ数

108 (COLORRES)			デバイスの実際のカラー解像度を表す、ピクセル当たりのビット数

110 (PHYSICALWIDTH)
111 (PHYSICALHEIGHT)	物理的なページ全体の幅・高さ（デバイス単位）（印刷デバイス用）

112 (PHYSICALOFFSETX)
113 (PHYSICALOFFSETY)	物理的なページの左辺・上辺から印刷可能領域の左辺・上辺までの距離（デバイス 単位）（印刷デバイス用）

114 (SCALINGFACTORX)
115 (SCALINGFACTORY)	x軸・y軸のスケーリングファクター

116 (VREFRESH)			Windows NT のみ：現在のディスプレイ出力の垂直周波数 (Hz)。0 または 1 はディスプレイのデフォル ト周波数を示します。

117 (DESKTOPVERTRES)
118 (DESKTOPHORZRES)	Windows NT のみ：仮想デスクトップの高さ・幅（ピクセル単位）

119 (BLTALIGNMENT)		Windows NT のみ：デバイスに適した水平方向のアラインメント。適したアラインメントが特にないときは 0。

戻り値

取得された情報が返ります。
