关于SetWindowOrgEx和SetViewPortOrgEx之区别

http://topic.csdn.net/u/20120409/02/f13fa322-f95d-4491-92e5-ef44c7223a35.html?seed=944436769&r=78183266#r_78183266
看到了楼主的提问仔细研究了一下这两个函数的区别,同时也防止自己忘记。
视口:
基于设备坐标的,就是视口的(0,0)即对应设备坐标的(0,0)。
窗口:
基于逻辑坐标的,即窗口坐标(0,0)对应逻辑坐标(0,0)。在一般情况下,两者的原点重叠,只是量度单位不同。
只是,在使用SetViewportOrgEx()函数或SetWindowsOrgEx()函数会分别改变两者的原点。
直观一点
SetViewportOrgEx()函数是客户区不动,图像的原点坐标移动。
SetWindowsOrgEx()函数是图像的原点坐标不动,客户区移动。
另外
映射方式的不同会使得两者的范围不同。
如果还有不理解的话也很正常,分别使用SetViewportOrgEx()函数和SetWindowsOrgEx()函数设置坐标后,用TextOut()函数输出字符串。通过查看字符串在客户区的实际位置便可以稍微清晰的理解。
下面给出我实验的结果来验证这一点
下面的图片是原始图片

图1 原始图片

图2 使用SetViewPortOrgEx调整的效果
这里我们使用了SetViewPortOrgEx来调整视口,可以知道调整视口的操作其实就是将图像的原点移动到你所指定的坐标

 
图3 使用SetWindowOrgEx调整的效果
这里我们可以知道,使用了SetWindowOrgEx调整之后发现客户区的位置动了,调整到指定的坐标上去了。
 
总结:
SetViewPortOrgEx动的是图像,也就是说将图像进行移动
SetWindowOrgEx动的是客户区,也就是说将客户区进行移动
这下理解它们的区别了吧。Mark
下面给出我的示例代码:
http://download.csdn.net/detail/xizero00/4211590

                
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用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` 函数实现的,具体细节可以参考代码注释。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值