• GDI 映射模式(11)


    概述

    调用 SetMapMode 函数可以设置映射模式:

    int SetMapMode(  
        HDC hdc,           // 设备环境句柄
        int fnMapMode   // 要设置的映射模式
    );

    同样,调用 GetMapMode 函数可以获取映射模式:

    int GetMapMode(
        HDC hdc   // 设备环境句柄
    );
    

    注:

    • 默认情况下,映射模式是 MM_TEXT,以像素为单位操作。
    • 映射模式的逻辑坐标只对以设备环境句柄为参数的 GDI 函数有效,非 GDI 函数将继续使用设备坐标

    设备坐标系统

    1. 屏幕坐标系统:屏幕左上角坐标为(0,0)
    2. 全窗口坐标系统:窗口边框左上角坐标为(0,0)
    3. 设备坐标系统:客户区左上角坐标为(0,0)

    设备坐标和逻辑坐标

    设备坐标指视口坐标,逻辑坐标指窗口坐标

    在 MM_TEXT 映射模式下,逻辑坐标与设备坐标重合,更改映射模式后,逻辑坐标对设备坐标的映射方法将发生改变。

    xView=(xWin-xWinOrg)*(xViewExt/xWinExt)+xViewOrg

    yView=(yWin-yWinOrg)*(yViewExt/yWinExt)+yViewOrg

    窗口和视口

    调用 SetViewPortOrgEx 函数可以设置视口(设备坐标)的原点

    调用 SetWindowOrgEx 函数可以设置窗口(逻辑坐标)的原点

    (实际上,这两个函数是改变了设备坐标到逻辑坐标的映射方式,而设备坐标永远是(0,0))

    例如 SetViewPortOrgEx ( hdc, 40, 40 ) 其实是将设备坐标(40,40)映射到了逻辑坐标原点(0,0)

    例如 SetWindowOrgEx ( hdc, 40, 40 ) 其实是将逻辑坐标(40,40)映射到了设备坐标原点(0,0)

    坐标转换

    调用 LPToDP 函数可以将逻辑坐标转换成设备坐标

    调用 DPToLP 函数可以将设备坐标转换成逻辑坐标

    各同向性和各异向性映射模式

    当第一次指定各同向性(MM_ISOTROPIC)和各异向性(MM_ANISOTROPIC)的映射模式时, 和 MM_LOMETRIC 映射模式有相同的效果

    调用 SetViewPortExtEx 函数可以设置视口(设备坐标)区域的大小(仅在各同向性(MM_ISOTROPIC)和各异向性(MM_ANISOTROPIC)的映射模式中起作用)

    调用 SetWindowExtEx 函数可以设置窗口(逻辑坐标)区域的大小(仅在各同向性(MM_ISOTROPIC)和各异向性(MM_ANISOTROPIC)的映射模式中起作用)

    (SetWindowExtEx 和 SetViewPortExtEx 函数,必须先后都调用,SetWindowExtEx 最好在 SetViewPortExtEx 前调用,这两个函数的本质是设置一种从逻辑坐标到设备坐标的缩放比例,实际上最终要转换到用以下两个公式来换算逻辑坐标位置映射到的设备坐标位置)

    xView=(xWin-xWinOrg)*(xViewExt/xWinExt)+xViewOrg

    yView=(yWin-yWinOrg)*(yViewExt/yWinExt)+yViewOrg

    MM_ISOTROPIC 和 MM_ANISOTROPIC 的区别:

    MM_ISOTROPIC 会将横纵坐标的缩放比例保持一致(以比例较小的为标准),故当逻辑区域大小改变的时候,图形不会发生拉伸现象,会保持横纵缩放比例一致。

    MM_ANISOTROPIC 不会将横纵坐标缩放比例保持一致,故当逻辑区域大小改变的时候,图形将可能会发生拉伸现象。

    WHATSIZE 示例程序

    #include <windows.h>
    #include <strsafe.h>
    
    void Show(HWND hwnd, HDC hdc, int xText, int yText, int iMapMode, LPCTSTR szMapMode) {
    	TCHAR szBuffer[60];
    	size_t ccLength;
    	RECT rcClient;
    
    	SaveDC(hdc);
    	SetMapMode(hdc, iMapMode);
    	GetClientRect(hwnd, &rcClient);
    	DPtoLP(hdc, (LPPOINT)&rcClient, 2);
    	RestoreDC(hdc, -1);
    
    	StringCchPrintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), TEXT("%-20s %7d %7d %7d %7d"), szMapMode, rcClient.left, rcClient.right, rcClient.top, rcClient.bottom);
    	StringCchLength(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), &ccLength);
    	TextOut(hdc, xText, yText, szBuffer, ccLength);
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    	
    	HDC hdc;
    	static int cxChar, cyChar;
    	PAINTSTRUCT ps;
    	TEXTMETRIC tm;
    	static TCHAR szHeading[] = TEXT("Mapping Mode            Left   Right     Top  Bottom");
    	static TCHAR szUndLine[] = TEXT("------------            ----   -----     ---  ------");
    	size_t ccLength;
    
    	switch (message) {
    	case WM_CREATE:
    		hdc = GetDC(hwnd);
    		SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    		
    		GetTextMetrics(hdc, &tm);
    		cxChar = tm.tmAveCharWidth;
    		cyChar = tm.tmHeight + tm.tmExternalLeading;
    
    		ReleaseDC(hwnd, hdc);
    		return 0;
    
    	case WM_PAINT:
    		hdc = BeginPaint(hwnd, &ps);
    
    		SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    		SetMapMode(hdc, MM_ANISOTROPIC);
    		SetWindowExtEx(hdc, 1, 1, NULL);
    		SetViewportExtEx(hdc, cxChar, cyChar, NULL);
    
    		StringCchLength(szHeading, sizeof(szHeading) / sizeof(TCHAR), &ccLength);
    		TextOut(hdc, 1, 1, szHeading, ccLength);
    
    		StringCchLength(szUndLine, sizeof(szUndLine) / sizeof(TCHAR), &ccLength);
    		TextOut(hdc, 1, 2, szUndLine, ccLength);
    
    		Show(hwnd, hdc, 1, 3, MM_TEXT, TEXT("TEXT (pixels)"));
    		Show(hwnd, hdc, 1, 4, MM_LOMETRIC, TEXT("LOMETRIC (.1 mm)"));
    		Show(hwnd, hdc, 1, 5, MM_HIMETRIC, TEXT("HIMETRIC (.01 mm)"));
    		Show(hwnd, hdc, 1, 6, MM_LOENGLISH, TEXT("LOENGLISH (.01 in)"));
    		Show(hwnd, hdc, 1, 7, MM_HIENGLISH, TEXT("HIENGLISH (.001 in)"));
    		Show(hwnd, hdc, 1, 8, MM_TWIPS, TEXT("TWIPS (1 / 1440 in)"));
    
    		EndPaint(hwnd, &ps);
    		return 0;
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    
    	}
    	
    	return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    	
    	LPCTSTR lpszClassName = TEXT("WHATSIZE");
    	LPCTSTR lpszWindowName = TEXT("WHATSIZE Program");
    	WNDCLASS wndclass;
    	HWND hwnd;
    	MSG msg;
    
    	wndclass.cbClsExtra = 0;
    	wndclass.cbWndExtra = 0;
    	wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	wndclass.hInstance = hInstance;
    	wndclass.lpfnWndProc = WndProc;
    	wndclass.lpszClassName = lpszClassName;
    	wndclass.lpszMenuName = NULL;
    	wndclass.style = CS_HREDRAW | CS_VREDRAW;
    
    	if (!RegisterClass(&wndclass)) {
    		MessageBox(NULL, TEXT("window class registering failed!"), TEXT("Error"), MB_ICONERROR);
    		return 0;
    	}
    
    	hwnd = CreateWindow(
    		lpszClassName,
    		lpszWindowName,
    		WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		NULL,
    		NULL,
    		hInstance,
    		NULL
    	);
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    
    	while (GetMessage(&msg, NULL, 0, 0)) {
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return msg.wParam;
    }
  • 相关阅读:
    Extjs combobox设置默认值
    sql 游标循环遍历
    .NET中的DES对称加密
    Asp.Net生命周期
    浅谈C#随机数发生器
    面向对象-多态 附抽象
    c#常用的一些命名空间
    c#面向对象编程基础
    string应用
    [自习任我行]第二阶段任务跟踪10
  • 原文地址:https://www.cnblogs.com/yenyuloong/p/9138026.html
Copyright © 2020-2023  润新知