procedure TForm1.FormPaint(Sender: TObject);
var
  ADC:HDC;
  ARect:TRect;
begin
  ADC:=GetDC(Self.Handle);
  Self.Repaint;
  //设置映射模式
  SetMapMode(ADC,MM_LOMETRIC);
  //设置坐标原点
  SetViewportOrgEx(ADC,200,200,nil);
  //画X,Y轴
  MoveToEx(ADC,0,0,nil);
  LineTo(ADC,100,0);
  MoveToEx(ADC,0,0,nil);
  LineTo(ADC,0,100);
  ReleaseDC(Self.Handle,ADC);
end;procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  APoint:TPoint;
  ADC:HDC;
  scale:Double;
begin
  lb_Mouse.Caption:=Format('X=%d Y=%d',[X,Y]) ;
  APoint:=Point(X,Y);
  ADC:=GetDC(Self.Handle);
  这里如何实现将鼠标位置转换为 MM_LOMETRIC 模式下的位置
  即显示相对于新坐标点的位置,单位应该是毫米
  if Windows.DPtoLP(ADC,APoint,1) then
    lb_MapPoint.Caption:=Format('X=%d Y=%d',[APoint.X,APoint.Y])
  else
    lb_MapPoint.Caption:='0,0'   ;
  ReleaseDC(Self.Handle,ADC);
end;

解决方案 »

  1.   

    首先告诉你,遗憾的是,Windows的消息传回的鼠标坐标,都是物理坐标,不是逻辑坐标。
    也就是说,传回的数值都是以像素为单位的。下来吗,我就要介绍大名鼎鼎的GetDeviceCaps 函数function GetDeviceCaps(hdc: HDC; nIndex:Integer): Integer; sdtcall;nIndex 有以下取值:
    HORZRES         Width, in pixels, of the screen.
    VERTRES         Height, in raster lines, of the screen.
    LOGPIXELSX Number of pixels per logical inch along the screen width.
    LOGPIXELSY Number of pixels per logical inch along the screen height.看到了没有? 我可以 获得 屏幕的分辨率,还有每英寸里有几个像素(一般会得到熟悉的96)
    这样你就可以获得 你的屏幕的 英寸数,然后转化成 millimeter 就可以了。1英寸 = 25.4 毫米 这个方法可能有纰漏,但应该能解决你的问题。
      

  2.   

    用GetDeviceCaps方式可以得到屏幕的毫米数和象素数,但在绘图时坐标都是毫米,在选择绘制好的图形时,鼠标的位置都是象素,在将鼠标位置 乘以 (1象素是多少毫米)后有较大的误差。现在就是想如何避免这种误差。
      

  3.   

    我想了这样一个办法.如指定绘图区为A4 210*229mm
    先指定绘图的BitMap 的宽度为4000pix ,用黑色填充然后坐标映射模式设置为毫米
    绘制一个(0,0,210,229)的白色绘图区现在主要是想知道在绘图区中,每个象素对应的毫米数.
    首先取到210毫米到底在屏幕上显示了多少象素
    用一个循环,从0点开始,取每个X轴上象素点的颜色,如果遇到了黑色则结束,这时就知道在毫米映射模式下210mm
    是多少象素了.
    创建一个数组 APixArr:Array of Integer; Setlength(APixArr,象素宽度)然后在毫米映射模式下,从0开始,每个偶数毫米画一个1mm宽的竖线
    用一个循环,从0点开始,取每个X轴上象素点的颜色,通过白,黑色交替来得到APixArr中每个象素对应的毫米位置这里,鼠标在绘图区移动时,直接要数组中查找就可以得到对应的毫米数了.