windows编程之几个坐标,坐标系的概念

利用GDI绘图的时候需要明白几个概念 设备坐标与逻辑坐标的区别,viewPort跟windowsPort的区别
<1>设备坐标跟逻辑坐标
设备坐标包括三种,客户区坐标,窗口坐标,屏幕坐标,它的特点是以左上角为原点,x轴向右递增,y轴向下递增,单位是像素。
逻辑坐标默认情况下跟设备坐标重合,采用像素为单位,但是逻辑坐标的单位并不一定是像素,它可以是具体的物理度量单位,包括mm,inch。我们再绘图的时候采用的都是逻辑单位,windows会把这些逻辑单位转换为像素单位。


<2>viewPort 和 windowsPort
这两者的翻译是视口,窗口。视口是基于设备坐标(像素的),窗口是基于逻辑坐标的,默认情况下两者重合。但是可以设置视口坐标系的原点以及窗口坐标系的原点。这时候要理解两个函数 SetViewportOrg(x,y),SetWindowportOrg(x,y)。
SetViewportOrg(x,y):指定设备点(x,y)映射到逻辑点(0,0);//视口原点跟窗口原点匹配
SetWindowPortOrg(x,y):指定逻辑点(x,y)映射到设备点(0,0)//


注意点:
要注意区分视口坐标系原点跟视口原点的区别,窗口坐标系原点跟窗口原点的区别。
视口坐标系其实就是设备坐标系,它是固定不变的,因此设备原点永远是(0,0)。
视口原点是可变的,它默认处于设备原点,但是可以更改。
窗口坐标系指定了在窗口绘图时的参考点,参考点就是窗口坐标系的原点。
窗口原点默认等于窗口坐标系原点,但是窗口原点可以改变。
窗口原点永远跟视口原点匹配映射。//这个是最主要的


根据公式:
xViewport = (xWindow - xWinOrg)× xViewExt /xWinExt + xViewOrg;
yViewport = (yWindow - yWinOrg)× yViewExt /yWinExt + yViewOrg;


从这个公式可以看到 逻辑点 (xWinOrg,yWinOrg)映射到 (xViewOrg,yViewOrg)从而证明了窗口原点永远跟视口原点匹配映射。

示例代码:

#include <Windows.h>
#include<stdio.h>
#pragma comment(lib, "winmm.lib")

LRESULT CALLBACK WndProc(
 HWND hwnd,      // handle to window
 UINT uMsg,      // message identifier
 WPARAM wParam,  // first message parameter
 LPARAM lParam   // second message parameter
 );




int WINAPI WinMain(
	HINSTANCE hInstance,      // handle to current instance
	HINSTANCE hPrevInstance,  // handle to previous instance
	LPSTR lpCmdLine,          // command line
	int nCmdShow              // show state
 )
{
	static TCHAR szAppName[]=TEXT("HelloWin");
	HWND hwnd;
	MSG msg;


	 WNDCLASS wndcls;
	 wndcls.cbClsExtra=0;
	 wndcls.cbWndExtra=0;
	 wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	 wndcls.hCursor=LoadCursor(NULL,IDC_ARROW);
	 wndcls.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	 wndcls.hInstance=hInstance;
	 wndcls.lpfnWndProc=WndProc;
	 wndcls.lpszClassName=szAppName;
	 wndcls.lpszMenuName=NULL;
	 wndcls.style=CS_HREDRAW | CS_VREDRAW;


	 if(!RegisterClass(&wndcls))
	 {
		MessageBox(NULL,TEXT("error"),szAppName,MB_OKCANCEL);
		return 0;
	 }


	hwnd=CreateWindow(szAppName,TEXT("the hello 


program!"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
	ShowWindow(hwnd,SW_SHOWNORMAL);
	UpdateWindow(hwnd);


	 while(GetMessage(&msg,NULL,0,0))
	 {
	  TranslateMessage(&msg);
	  DispatchMessage(&msg);
	 }
	 return 0;
}


LRESULT CALLBACK WndProc(
 HWND hwnd,      // handle to window
 UINT uMsg,      // message identifier
 WPARAM wParam,  // first message parameter
 LPARAM lParam   // second message parameter
 )
{
	 HDC hdc;
	 PAINTSTRUCT ps;
	 RECT rect;
	 POINT pt1,pt2;
	 switch(uMsg)
	 {
		 case WM_PAINT:
			hdc = GetDC(hwnd);
			GetClientRect(hwnd,&rect);
			SetViewportOrgEx(hdc,rect.right/2,rect.bottom/2,NULL);
			SetWindowOrgEx(hdc,-rect.right/2,-rect.bottom/2,NULL);
			Rectangle(hdc,0,0,-100,-100);
			GetViewportOrgEx(hdc,&pt1);
			GetWindowOrgEx(hdc,&pt2);
			ReleaseDC(hwnd,hdc);
			return 0;
		
		 case WM_DESTROY:
			 PostQuitMessage(0);
			 return 0;
		 }
	 return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
可以调试程序观测程序运行时候点pt1,pt2对应的值。通过对比就很容易发现问题,拨开迷雾见晴天。

你可能感兴趣的:(窗口,视口,设备坐标,视口原点,窗口原点)