为什么SetWindowExtEx的缩放可能是错误的?

时间:2016-05-05 01:34:53

标签: windows winapi

我正在尝试使用MM_ANISTROPIC缩放图像/文本等,我所做的是以下(顺便说一句,如果语法有点奇怪,它最初来自delphi,所以将以下内容视为伪代码)

我希望下面的代码可以生成一个矩形,它是PaintBox宽度的70%和高度的30%,但它没有,相反它显然太小了。

SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,100,100,0);
SetViewportExtEx(hdc,70,30,0);
Rectangle(hdc, 0,0,PaintBox.width-1,PaintBox.Height-1);

另一方面,如果我更改代码以便SetWindowExtEx有91而不是100作为其参数(如下所示)那么它可以工作,这对我来说毫无意义...... < / p>

SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,91,91,0);
SetViewportExtEx(hdc,70,30,0);
Rectangle(hdc, 0,0,PaintBox.width-1,PaintBox.Height-1);

我的理智测试案例是添加以下伪代码

SetMapMode(hdc,MM_TEXT);
DrawLine(hdc,Round(PaintBox.width*0.7),0,Round(PaintBox.width*0.7),PaintBox.Height-1);
DrawLine(hdc,0,Round(PaintBox.height*0.3),PaintBox.width-1,Round(PaintBox.height*0.3));

我原本希望这会覆盖原始Rectangle的下边缘/下边缘,但除非我使用91,91 SetWindowExtEx,否则它不会。

任何人都可以复制这个吗?

进一步编辑:这是我之前给出伪代码的确切原始代码,以使非delphi用户更容易访问该问题,但我的一位评论者想要完整的代码,看看我的争论是否是delphi quirk是真的或不。

整个项目由一个VCL表单组成,其上面放置一个矩形的绘图框,因此周围有空格,其onPaint事件设置为下面的代码,结果为this image:

procedure TForm11.PaintBox2Paint(Sender: TObject);
    var
      hdc:THandle;
      res:TPoint;

    procedure SetupMapMode;
    begin
      SetMapMode(hdc,MM_ANISOTROPIC);
      SetWindowExtEx(hdc,100,100,0);
      SetViewportExtEx(hdc,70,30,0);
    //  These lines are required when we're painting to a TPaintBox but can't be used
    //  if we're paiting to a TPanel and they were NOT in my original question but only
    //  got added as part of the answer
    //  SetViewportOrgEx(hdc,PaintBox2.Left,PaintBox2.Top,@ZeroPoint);
    //  SetWindowOrgEx(hdc,0,0,@ZeroPoint);
    end;

    begin
      //draw a rectangle to frame the Paintbox Surface
      PaintBox2.Canvas.Pen.Style:=psSolid;
      PaintBox2.Canvas.Pen.width:=2;
      PaintBox2.Canvas.Pen.Color:=clGreen;
      PaintBox2.Canvas.Brush.Style:=bsClear;
      PaintBox2.Canvas.Rectangle(0,0,PaintBox2.Width-1,PaintBox2.Height-1);
      PaintBox2.Canvas.Brush.Style:=bsSolid;

      //initialize convenience variable
      hdc:=PaintBox2.Canvas.Handle;
      SetTextAlign(hdc,TA_LEFT);

    //as doing things to the PaintBox2.Canvas via Delphi's interface tends to reset
    //everything, I'm ensuring the map mode gets set **immediately** before
    //each drawing call
      SetupMapMode;
    ///  Draw Text at the bottom of the PaintBox2.Canvas (though as it's mapped it
    ///  SHOULD be 1/3 of the way down and much smaller instead)
      TextOut(hdc,200,PaintBox2.Height-PaintBox2.Canvas.TextHeight('Ap'),'Hello, World!',13);
      PaintBox2.Canvas.Pen.Color:=clblue;
      PaintBox2.Canvas.Brush.Style:=bsClear;
    //ensure it's set before doing the rectangle
      SetupMapMode;
    // Redraw the same rectangle as before but in the mapped mode
      Rectangle(hdc, 0,0,PaintBox2.Width-1,PaintBox2.Height-1);
      PaintBox2.Canvas.Brush.Style:=bsSolid;
    //reset the map mode to normal
      SetMapMode(hdc,MM_Text);
    //draw text at the "same" position as before but unmapped...
      TextOut(hdc,200,PaintBox2.Height-PaintBox2.Canvas.TextHeight('Ap'),'Goodbye, World!',15);

    //Draw lines exactly at 70% of the way across and 30% of the way down
    //if this works as expected they should overwrite the right and bottom
    //borders of the rectangle drawn in the mapped mode
      PaintBox2.Canvas.Pen.Color:=RGB(0,255,255);
      PaintBox2.Canvas.MoveTo(Round(PaintBox2.Width*0.7),0);
      PaintBox2.Canvas.LineTo(Round(PaintBox2.Width*0.7),PaintBox2.Height);
      PaintBox2.Canvas.MoveTo(0,Round(PaintBox2.Height*0.3));
      PaintBox2.Canvas.LineTo(PaintBox2.Width,Round(PaintBox2.Height*0.3));
    end;

1 个答案:

答案 0 :(得分:0)

好的,我不知道为什么以下是必要的 - 它可能是Delphi的怪癖,我使用TPaintBox的事实是TGraphicControl而不是Component,或者如果我&# 39; m错过了关于整个映射模式如何工作的一些基本概念,但是如果我添加以下代码:

ZeroPoint:=TPoint.Zero;
SetViewportOrgEx(hdc,PaintBox1.Left,PaintBox1.Top,@ZeroPoint);
SetWindowOrgEx(hdc,0,0,@ZeroPoint);

然后它按预期显示。任何人都有任何解释为什么这是必要的?

编辑:好的,我已经得到了PARTIAL的解释。它与我作为TPaintBox绘制的控件有关,它是一个TGraphic控件而不是TWinControl。即:

  

TGraphicControl是所有轻量级控件的基类。

     

TGraphicControl支持简单的轻量级控件,无需接受键盘输入或包含其他控件。由于轻量级控件不包装Windows屏幕对象,因此它们比基于TWinControl的控件更快,用户更少。

因此,虽然他们看起来有一个单独的画布,但我有这种偷偷摸摸的感觉,他们真的在分享这种形式的画布,这就是为什么当我切换到TWinControl后代时,它拥有自己的Windows DC,然后显示按预期工作,而不设置ViewpointOrg。

毕竟这是德尔福的怪癖......!