关于SetWindowOrgEx、SetViewportOrgEx、SetViewportExtEx 和SetWindowExtEx 详解

关于SetWindowOrgExSetViewportOrgExSetViewportExtEx SetWindowExtEx 详解

 

1、  SetWindowOrgEx是设置窗口的原点坐标。

 

例如:

         Ellipse(hdc,-100,-100,100,100);

         MoveToEx(hdc,-200,0,NULL);

         LineTo(hdc,200,0);

         MoveToEx(hdc,0,-200,NULL);

         LineTo(hdc,0,200);

         MoveToEx(hdc,0,0,NULL);

         LineTo(hdc,100,100);

运行程序的效果为:

 

修一下程序为:

         SetWindowOrgEx(hdc,-100,-100,NULL);

         Ellipse(hdc,-100,-100,100,100);

         MoveToEx(hdc,-200,0,NULL);

         LineTo(hdc,200,0);

         MoveToEx(hdc,0,-200,NULL);

         LineTo(hdc,0,200);

         MoveToEx(hdc,0,0,NULL);

         LineTo(hdc,100,100);

运行效果为:

 

得出结论:SetWindowOrgEx是设置窗口原点坐标的大小

 

2、  SetViewportOrgEx设置视口原点坐标。

我们将上面程序再次修改一下:

         SetViewportOrgEx (hdc,100,100,NULL);

         Ellipse(hdc,-100,-100,100,100);

         MoveToEx(hdc,-200,0,NULL);

         LineTo(hdc,200,0);

         MoveToEx(hdc,0,-200,NULL);

         LineTo(hdc,0,200);

         MoveToEx(hdc,0,0,NULL);

         LineTo(hdc,100,100);

效果很上面的一样:

      

 

得出结论:SetViewPortOrgEx是设视口原点坐标的大小,也就是客户区的原点大小。在默认的情况下,客户区的原点为左上角坐标为(0,0)。调用SetViewportOrgEx (hdc,100,100,NULL)就把客户的原点坐标设置为(100,100),那么原来客户区的左上角的坐标就变为了(-100-100(在映射模式为MM_TEXT)

3 SetWindowExtEx  用于设置逻辑坐标范围。

SetViewPortExtEx, 用于设置设备坐标范围。

注意:1、上面的两个函数的调用,只有在映射模式为MM_ANISOTROPIC MM_ISOROPIC下才有作用,在其他的模式下将被忽略。

2、             必须在调用SetViewPortExtEx之前调用SetWindowExtEx,以便最有效地使用显示区域中的空间。

 修改上面的代码:

           SetMapMode(hdc,MM_ANISOTROPIC);

         SetWindowExtEx(hdc,200,200,NULL);//将窗口的逻辑坐标X0 200Y轴设置为0 200

         //将视口原点设置为客户区的中心点上

         SetViewportOrgEx(hdc,rectClient.right / 2,rectClient.bottom / 2,NULL);

         //将窗口的设备坐标X 0  rectClient.right,Y0 rectClient.bottom

         SetViewportExtEx(hdc,rectClient.right,rectClient.bottom,NULL);

 

         Ellipse(hdc,-100,-100,100,100);

         MoveToEx(hdc,-200,0,NULL);

         LineTo(hdc,200,0);

         MoveToEx(hdc,0,-200,NULL);

         LineTo(hdc,0,200);

         MoveToEx(hdc,0,0,NULL);

         LineTo(hdc,100,100);

效果图为:

 

 

相关的文章文章链接:

http://blog.csdn.net/typecool/archive/2010/09/16/5887367.aspx

http://www.ucancode.net/faq/Coordinate-SetViewportOrg-SetWindowExt-SetViewportExt-SetMapMode.htm

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是使用GDI绘制抛物线和双曲线的示例代码,包括放大、缩小和移动功能: ```c++ #include <windows.h> #include <cmath> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("Parabola and Hyperbola"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Parabola and Hyperbola"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClient, cyClient; static int xCenter, yCenter; static double scaleX = 1.0, scaleY = 1.0; static double xMove = 0.0, yMove = 0.0; static POINT ptPrev; static bool bDragging = false; switch (message) { case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); xCenter = cxClient / 2; yCenter = cyClient / 2; return 0; case WM_KEYDOWN: switch (wParam) { case VK_ADD: scaleX *= 1.1; scaleY *= 1.1; InvalidateRect(hwnd, NULL, TRUE); return 0; case VK_SUBTRACT: scaleX /= 1.1; scaleY /= 1.1; InvalidateRect(hwnd, NULL, TRUE); return 0; case VK_LEFT: xMove -= 10.0 / scaleX; InvalidateRect(hwnd, NULL, TRUE); return 0; case VK_RIGHT: xMove += 10.0 / scaleX; InvalidateRect(hwnd, NULL, TRUE); return 0; case VK_UP: yMove -= 10.0 / scaleY; InvalidateRect(hwnd, NULL, TRUE); return 0; case VK_DOWN: yMove += 10.0 / scaleY; InvalidateRect(hwnd, NULL, TRUE); return 0; } return 0; case WM_LBUTTONDOWN: SetCapture(hwnd); ptPrev.x = LOWORD(lParam); ptPrev.y = HIWORD(lParam); bDragging = true; return 0; case WM_MOUSEMOVE: if (bDragging) { xMove += (LOWORD(lParam) - ptPrev.x) / scaleX; yMove += (HIWORD(lParam) - ptPrev.y) / scaleY; InvalidateRect(hwnd, NULL, TRUE); ptPrev.x = LOWORD(lParam); ptPrev.y = HIWORD(lParam); } return 0; case WM_LBUTTONUP: ReleaseCapture(); bDragging = false; return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // set up coordinate transformation SetMapMode(hdc, MM_ANISOTROPIC); SetViewportOrgEx(hdc, xCenter, yCenter, NULL); SetWindowExtEx(hdc, cxClient, -cyClient, NULL); SetViewportExtEx(hdc, (int)(cxClient / scaleX), (int)(cyClient / scaleY), NULL); SetWindowOrgEx(hdc, (int)(-xMove * scaleX), (int)(yMove * scaleY), NULL); // draw parabola MoveToEx(hdc, -1000, (int)(1000 * 1000), NULL); for (int x = -1000; x <= 1000; x++) { int y = (int)(-x * x / 1000.0); LineTo(hdc, x, y); } // draw hyperbola MoveToEx(hdc, -1000, 0, NULL); for (int x = -1000; x <= -1; x++) { int y = (int)(1000 * sqrt(1.0 + x * x / 1000.0)); LineTo(hdc, x, y); } for (int x = 1; x <= 1000; x++) { int y = (int)(-1000 * sqrt(1.0 + x * x / 1000.0)); LineTo(hdc, x, y); } EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } ``` 在上述代码中,我们使用 `SetMapMode` 和 `SetViewportOrgEx` 等 GDI 函数设置了坐标系的变换,使得我们可以方便地实现放大、缩小和移动功能。抛物线和双曲线的绘制都是通过 `LineTo` 函数实现的,具体细节可以参考代码注释。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值