<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創(chuàng)未來!
    隨筆 - 160, 文章 - 0, 評(píng)論 - 40, 引用 - 0
    數(shù)據(jù)加載中……

    坐標(biāo)空間

    Win32應(yīng)用程序設(shè)計(jì)接口(API)使用四種坐標(biāo)空間:世界坐標(biāo)系空間、頁面空間、設(shè)備空間、和物理設(shè)備空間。應(yīng)用程序運(yùn)用世界坐標(biāo)系空間對(duì)圖形輸出進(jìn)行旋轉(zhuǎn)、斜切或者反射(一般坐標(biāo)系完不成這些特殊的功能)。
    Win32 API把世界坐標(biāo)系空間和頁面空間稱為邏輯空間;最后一種坐標(biāo)空間(即物理設(shè)備空間)通常指應(yīng)用程序窗口的客戶區(qū);但是它也包括整個(gè)桌面、完整的窗口(包括框架、標(biāo)題欄和菜單欄)或打印機(jī)的一頁或繪圖儀的一頁紙。
    如果該應(yīng)用程序調(diào)用了SetWorldTransform函數(shù),那么映射就從應(yīng)用程序的世界坐標(biāo)系空間開始;否則,映射在頁面空間中進(jìn)行。
    下面有一個(gè)從MSDN中拷貝出來的例子如下:
    enum TransformStyle { SCALE, TRANSLATE, ROTATE, SHEAR, REFLECT, NORMAL};

    void CXXXXView::TransformAndDraw(int iTransform, HWND hWnd)
    {
        HDC hDC;
        XFORM xForm;
        RECT rect;
     
        // Retrieve a DC handle for the application's window.
     
        hDC = ::GetDC(hWnd);
     
        // Set the mapping mode to LOENGLISH. This moves the
        // client area origin from the upper left corner of the
        // window to the lower left corner (this also reorients
        // the y-axis so that drawing operations occur in a true
        // Cartesian space). It guarantees portability so that
        // the object drawn retains its dimensions on any display.

        SetGraphicsMode(hDC, GM_ADVANCED);
        SetMapMode(hDC, MM_LOENGLISH);
     
        // Set the appropriate world transformation (based on the
        // user's menu selection).
     
        switch (iTransform)
        {
            case SCALE:        // Scale to 1/2 of the original size.
                xForm.eM11 = (FLOAT) 0.5;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 0.5;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case TRANSLATE:   // Translate right by 3/4 inch.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 75.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case ROTATE:      // Rotate 30 degrees counterclockwise.
                xForm.eM11 = (FLOAT) 0.8660;
                xForm.eM12 = (FLOAT) 0.5000;
                xForm.eM21 = (FLOAT) -0.5000;
                xForm.eM22 = (FLOAT) 0.8660;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case SHEAR:       // Shear along the x-axis with a
                              // proportionality constant of 1.0.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 1.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case REFLECT:     // Reflect about a horizontal axis.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) -1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
     
            case NORMAL:      // Set the unity transformation.
                xForm.eM11 = (FLOAT) 1.0;
                xForm.eM12 = (FLOAT) 0.0;
                xForm.eM21 = (FLOAT) 0.0;
                xForm.eM22 = (FLOAT) 1.0;
                xForm.eDx  = (FLOAT) 0.0;
                xForm.eDy  = (FLOAT) 0.0;
                SetWorldTransform(hDC, &xForm);
                break;
      default:
       break;
        }
     
        // Find the midpoint of the client area.
     
        ::GetClientRect(hWnd, (LPRECT) &rect);
        DPtoLP(hDC, (LPPOINT) &rect, 2);
     
        // Select a hollow brush.
     
        SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
     
        // Draw the exterior circle.
     
        Ellipse(hDC, (rect.right / 2 - 100), (rect.bottom / 2 + 100),
            (rect.right / 2 + 100), (rect.bottom / 2 - 100));
     
        // Draw the interior circle.
     
        Ellipse(hDC, (rect.right / 2 -94), (rect.bottom / 2 + 94),
            (rect.right / 2 + 94), (rect.bottom / 2 - 94));
     
        // Draw the key.
     
        Rectangle(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 113),
            (rect.right / 2 + 13), (rect.bottom / 2 + 50));
        Rectangle(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 96),
            (rect.right / 2 + 13), (rect.bottom / 2 + 50));
     
        // Draw the horizontal lines.
     
        MoveToEx(hDC, (rect.right/2 - 150), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 - 16), (rect.bottom / 2 + 0));
     
        MoveToEx(hDC, (rect.right / 2 - 13), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 + 13), (rect.bottom / 2 + 0));
     
        MoveToEx(hDC, (rect.right / 2 + 16), (rect.bottom / 2 + 0), NULL);
        LineTo(hDC, (rect.right / 2 + 150), (rect.bottom / 2 + 0));
     
        // Draw the vertical lines.
     
        MoveToEx(hDC, (rect.right/2 + 0), (rect.bottom / 2 - 150), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 - 16));
     
        MoveToEx(hDC, (rect.right / 2 + 0), (rect.bottom / 2 - 13), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 13));
     
        MoveToEx(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 16), NULL);
        LineTo(hDC, (rect.right / 2 + 0), (rect.bottom / 2 + 150));
     
        ::ReleaseDC(hWnd, hDC);
    }
    頁面空間到設(shè)備空間的轉(zhuǎn)換是原Windows接口的一部分,也是我們可以用代碼控制的一種轉(zhuǎn)換,頁面空間到設(shè)備空間的轉(zhuǎn)換所用的是兩個(gè)矩形的寬與高的比率,其中頁面空間中的矩形被稱為窗口,設(shè)備空間中的矩形被稱為視口,Windows把窗口原點(diǎn)映射到視口原點(diǎn),把窗口范圍映射到視口范圍,就完成了這種轉(zhuǎn)換。

    設(shè)備空間到物理空間的轉(zhuǎn)換有幾個(gè)獨(dú)特之處:它只限于平移,并由Windows的窗口管理部分控制,這種轉(zhuǎn)換的唯一用途是確保設(shè)備空間的原點(diǎn)被映射到物理設(shè)備上的適當(dāng)點(diǎn)上。沒有函數(shù)能設(shè)置這種轉(zhuǎn)換,也沒有函數(shù)可以獲取有關(guān)數(shù)據(jù)。因此我們不能人為干預(yù)。

    實(shí)際上我們需要完成的是從頁面空間到物理設(shè)備空間的映射,由于物理設(shè)備空間通常指應(yīng)用程序窗口的客戶區(qū),因此我們只用關(guān)注于從頁面空間到設(shè)備空間的映射就可以了。

    一旦應(yīng)用程序建立了設(shè)備描述表(DC),并立即開始調(diào)用GDI繪圖或輸出函數(shù),則運(yùn)用默認(rèn)頁面空間到設(shè)備空間的轉(zhuǎn)換和設(shè)備空間到客戶區(qū)的轉(zhuǎn)換(在應(yīng)用程序調(diào)用SetWorldTransform函數(shù)之前,不會(huì)出現(xiàn)世界坐標(biāo)空間到頁面空間的轉(zhuǎn)換)。

    默認(rèn)頁面空間到設(shè)備空間的轉(zhuǎn)換結(jié)果是一對(duì)一的映射;即頁面空間上給出的一點(diǎn)映射到設(shè)備空間的一個(gè)點(diǎn)。正如前文講到的,這種轉(zhuǎn)換沒有以矩陣指定,而是通過把視口寬除以窗口寬,把視口高除以窗口高而得出的。在默認(rèn)的情況下,視口尺寸為1x1個(gè)象素,窗口尺寸為1x1頁單位。

    幾乎在所有的GDI函數(shù)中使用的坐標(biāo)值都是采用的邏輯單位。Windows必須將邏輯單位轉(zhuǎn)換為“設(shè)備單位”,即像素。Windows對(duì)所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函數(shù)和一些GDI函數(shù)(例如GetDeviceCaps函數(shù)),永遠(yuǎn)使用設(shè)備坐標(biāo)。“窗口”是基于邏輯坐標(biāo)的,邏輯坐標(biāo)可以是象素、毫米、英寸等單位;“視口”是基于設(shè)備坐標(biāo)(象素)的。通常,視口和客戶區(qū)是相同的。

    窗口(邏輯)坐標(biāo)轉(zhuǎn)換為視口(設(shè)備)坐標(biāo)的兩個(gè)公式:
    xViewport=(xWindow-xWinOrg)*xViewExt/xWinExt+xViewOrg
    yViewport=(yWindow-yWinOrg)*yViewExt/yWinExt+yViewOrg

    視口(設(shè)備)坐標(biāo)轉(zhuǎn)換為窗口(邏輯)坐標(biāo)的兩個(gè)公式:
    xWindow=(xViewPort-xViewOrg)*xWinExt/xViewExt+xWinOrg
    yWindow=(yViewPort-yViewOrg)*yWinExt/yViewExt+yWinOrg

    在MM_TEXT映射方式下邏輯坐標(biāo)和設(shè)備坐標(biāo)的相互轉(zhuǎn)換
    窗口(邏輯)坐標(biāo)轉(zhuǎn)換為視口(設(shè)備)坐標(biāo)的兩個(gè)公式:
    xViewport = xWindow-xWinOrg+xViewOrg
    yViewport = yWindow-yWinOrg+yViewOrg
    視口(設(shè)備)坐標(biāo)轉(zhuǎn)換為窗口(邏輯)坐標(biāo)的兩個(gè)公式:
    xWindow = xViewport-xViewOrg+xWinOrg
    yWindow = yViewport-yViewOrg+yWinOrg

    CDC中提供了兩個(gè)成員函數(shù)函數(shù)SetViewportOrg和SetWindowOrg,用來改變視口和窗口的原點(diǎn)。
    如果將視口原點(diǎn)設(shè)置為(xViewOrg,yViewOrg),則邏輯點(diǎn)(0,0)就會(huì)被映射為設(shè)備點(diǎn)(xViewOrg,yViewOrg)。如果將窗口原點(diǎn)改變?yōu)?xWinOrg,yWinOrg),則邏輯點(diǎn)(xWinOrg,yWinOrg)將會(huì)被映射為設(shè)備點(diǎn)(0,0),即左上角。
    不管對(duì)窗口和視口原點(diǎn)作什么改變,設(shè)備點(diǎn)(0,0)始終是客戶區(qū)的左上角。

    說一點(diǎn)自己的感悟:
    坐標(biāo)系有四種,上面介紹的很詳細(xì)了,就不多說了。
    對(duì)于很重要的從頁面坐標(biāo)到設(shè)備坐標(biāo)的轉(zhuǎn)換,頁面坐標(biāo)用邏輯單位表示,可以采用長度度量單位如米或英尺來與邏輯單位相掛鉤,也可以用像素來和邏輯單位掛鉤,而且我們說窗口;設(shè)備坐標(biāo)只用像素表示,而且我們說視口。因此從邏輯坐標(biāo)到設(shè)備坐標(biāo)有很多種映射方式:
    Mapping Mode Logical Unit Positive y-axis Extends...
    MM_TEXT 1 pixel Downward
    MM_HIMETRIC 0.01 mm Upward
    MM_TWIPS 1/1440 in Upward
    MM_HIENGLISH 0.001 in Upward
    MM_LOMETRIC 0.1 mm Upward
    MM_LOENGLISH 0.01 in Upward
    還有MM_ISOTROPIC(長度和寬度的比例因子一致)和MM_ANISOTROPIC(長寬比例因子可以不一致)。
    舉個(gè)例子來說,比如MM_HIMETRIC,每個(gè)邏輯單元代表0.01毫米,比如邏輯橫坐標(biāo)100,代表1毫米的長度,而對(duì)于設(shè)備坐標(biāo)(也可以說物理坐標(biāo))來說,如果分辨率是96dpi,那么也就是1英尺有96個(gè)像素,因此從1毫米先轉(zhuǎn)換為多少英尺,然后再轉(zhuǎn)換為多少個(gè)像素,就可以知道屏幕上在哪個(gè)位置顯示這個(gè)位置了。

    還需要注意的是,GDI函數(shù)都是用邏輯坐標(biāo)來計(jì)算的,而非GDI函數(shù)以及少部分GDI函數(shù)都是用設(shè)備坐標(biāo)也就是像素來表示的,設(shè)備坐標(biāo)只能用像素來計(jì)算。

     

     

    posted on 2008-02-23 19:18 so true 閱讀(743) 評(píng)論(0)  編輯  收藏 所屬分類: C&C++

    主站蜘蛛池模板: 日韩一级在线播放免费观看| 伊人婷婷综合缴情亚洲五月| 真正全免费视频a毛片| 国产亚洲精品精品国产亚洲综合| 日韩免费在线观看视频| 国产日本亚洲一区二区三区| 亚洲JIZZJIZZ中国少妇中文| 67194国产精品免费观看| 在线亚洲v日韩v| 亚洲一区二区三区电影| 国产又长又粗又爽免费视频| 久久精品无码精品免费专区| 亚洲heyzo专区无码综合| 国产成A人亚洲精V品无码| 在线观看免费为成年视频| 国产自国产自愉自愉免费24区| 一本色道久久88—综合亚洲精品 | 国产极品粉嫩泬免费观看 | 久久精品国产免费一区| 亚洲日韩乱码中文字幕| 亚洲国产精品乱码一区二区| 免费黄色一级毛片| 久久精品国产这里是免费| 成人午夜免费视频| 亚洲欧美成aⅴ人在线观看| 亚洲激情中文字幕| 国产亚洲精品看片在线观看 | 成在人线av无码免费高潮喷水| 日本亚洲色大成网站www久久| 亚洲AV成人无码久久精品老人| 免费看一级做a爰片久久| 在线看免费观看AV深夜影院| 中文在线免费视频| 美女视频黄频a免费大全视频| 亚洲AV无码成人专区| 亚洲自偷自拍另类12p| 亚洲尤码不卡AV麻豆| 免费久久精品国产片香蕉| 女人被免费视频网站| 精品久久久久成人码免费动漫 | 美女被免费喷白浆视频|