zoukankan      html  css  js  c++  java
  • Windows基础窗体编程

    Direct2D基于Windows窗体,因此必须了解一些基本的Windows窗体编程:

    首先,最基本的,可以使用Windows API写一个窗体:

    View Code
    #include <Windows.h>
    
    typedef LRESULT (* message_callback)(HWND, WPARAM, LPARAM);
    
    struct message_handler
    {
        UINT message;
        message_callback handler;
    };
    
    static message_handler s_handlers[] = 
    {
        {
            WM_PAINT, [] (HWND window, WPARAM, LPARAM) -> LRESULT
            {
                PAINTSTRUCT ps;
                BeginPaint(window, &ps);
                OutputDebugString(L"PAINT!\r\n");
                EndPaint(window, &ps);
                return 0;
            }
        }, 
        {
            WM_DESTROY, [] (HWND, WPARAM, LPARAM) -> LRESULT
            {
                PostQuitMessage(0);
                return 0;
            }
        }
    };
    
    int __stdcall wWinMain(HINSTANCE module, HINSTANCE, PWSTR, int)
    {
        WNDCLASS wc = {};
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wc.hInstance = module;
        wc.lpszClassName = L"window";
    
        wc.lpfnWndProc = [] (HWND window, UINT message, WPARAM wparam, LPARAM lparam) -> LRESULT
        {
            for (auto h = s_handlers; h != s_handlers + _countof(s_handlers); ++h)
            {
                if (message == h->message)
                {
                    return h->handler(window, wparam, lparam);
                }
            }
    
            return DefWindowProc(window, message, wparam, lparam);
        };
    
        RegisterClass(&wc);
    
        auto hwnd = CreateWindow(wc.lpszClassName, L"title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
            nullptr, nullptr, module, nullptr);
    
        MSG message;
        BOOL result;
        
        while (result = GetMessage(&message, 0, 0, 0))
        {
            if (result != -1)
            {
                DispatchMessage(&message);
            }
        }
    }

    然后,加入ATL库后,窗体编程的事件过程可以简化很多: 

    View Code
    #include <Windows.h>
    #include <atlbase.h>
    #include <atlwin.h>
    
    struct SampleWindow :
        CWindowImpl<SampleWindow, CWindow, CWinTraits<WS_OVERLAPPEDWINDOW | WS_VISIBLE>>
    {
        DECLARE_WND_CLASS_EX(L"window", CS_HREDRAW | CS_VREDRAW, -1);
        BEGIN_MSG_MAP(SampleWindow)
            MESSAGE_HANDLER(WM_PAINT, PaintHandler)
            MESSAGE_HANDLER(WM_DESTROY, DestroyHandler)
        END_MSG_MAP()
    
        LRESULT PaintHandler(UINT, WPARAM, LPARAM, BOOL&)
        {
            PAINTSTRUCT ps;
            BeginPaint(&ps);
            EndPaint(&ps);
            return 0;
        }
    
        LRESULT DestroyHandler(UINT, WPARAM, LPARAM, BOOL&)
        {
            PostQuitMessage(0);
            return 0;
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        window.Create(nullptr, 0, L"Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE);
    
        MSG message;
        BOOL result;
    
        while (result = GetMessage(&message, 0, 0, 0))
        {
            if (result != -1)
            {
                DispatchMessage(&message);
            }
        }
    }

    要加入D2D1,需要引入COM组件,然而,COM比较复杂,微软引用WRL来简化COM的一些引用计数之类的操作,以下是一个基本的D2D1示例(显示一个带颜色的窗体):

    View Code
    #include "Precompiled.h"
    #include <d2d1.h>
    #include <wrl.h>
    
    #pragma comment(lib, "d2d1")
    
    using namespace D2D1;
    using namespace Microsoft::WRL;
    
    struct SampleWindow
        : CWindowImpl<SampleWindow, CWindow, CWinTraits<WS_OVERLAPPEDWINDOW | WS_VISIBLE>>
    {
        ComPtr<ID2D1Factory> m_factory;
        ComPtr<ID2D1HwndRenderTarget> m_target;
    
        DECLARE_WND_CLASS_EX(L"My D2D1 Window", CS_HREDRAW | CS_VREDRAW, -1);
    
        BEGIN_MSG_MAP(SampleWindow)
            MESSAGE_HANDLER(WM_PAINT, PaintHandler)
            MESSAGE_HANDLER(WM_DESTROY, DestroyHandler)
            MESSAGE_HANDLER(WM_SIZE, SizeHandler)
            MESSAGE_HANDLER(WM_DISPLAYCHANGE, DisplayChangeHandler)
        END_MSG_MAP()
    
        LRESULT DisplayChangeHandler(UINT, WPARAM, LPARAM, BOOL&)
        {
            Invalidate();
            return 0;
        }
    
        LRESULT SizeHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
        {
            if (m_target)
            {
                if (m_target->Resize(SizeU(LOWORD(lparam), HIWORD(lparam))) != S_OK)
                {
                    m_target.Reset();
                }
            }
            return 0;
        }
    
        LRESULT PaintHandler(UINT, WPARAM, LPARAM, BOOL&)
        {
            PAINTSTRUCT ps;
            VERIFY(BeginPaint(&ps));
            Render();
            EndPaint(&ps);
            return 0;
        }
    
        LRESULT DestroyHandler(UINT, WPARAM, LPARAM, BOOL&)
        {
            PostQuitMessage(0);
            return 0;
        }
    
        void Invalidate()
        {
            VERIFY(InvalidateRect(nullptr, false))
        }
    
        void Create()
        {
            D2D1_FACTORY_OPTIONS fo = {};
    #ifdef DEBUG
            fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
    #endif
    
            D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, 
                              fo, 
                              m_factory.GetAddressOf());
            CreateDeviceIndependentResources();
            VERIFY(__super::Create(nullptr, 0, L"title"));
        }
    
        void CreateDeviceIndependentResources()
        {
        }
    
        void CreateDeviceResources()
        {
        }
    
        void Render()
        {
            if (!m_target)
            {
                RECT rect;
                VERIFY(GetClientRect(&rect));
    
                auto size = SizeU(rect.right, rect.bottom);
    
                m_factory->CreateHwndRenderTarget(RenderTargetProperties(), 
                                                  HwndRenderTargetProperties(m_hWnd, size), 
                                                  m_target.GetAddressOf());
                CreateDeviceResources();
                
            }
    
            if (!(m_target->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))
            {
                m_target->BeginDraw();
    
                Draw();
    
                if (m_target->EndDraw() == D2DERR_RECREATE_TARGET)
                {
                    m_target.Reset();
                }
            }
        }
    
        void Draw()
        {
            m_target->Clear(ColorF(1.0f, 1.0f, 0.0f));
        }
    };
    
    int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
    {
        SampleWindow window;
        window.Create();
    
        MSG msg;
        BOOL result;
        while (result = GetMessage(&msg, 0, 0, 0))
        {
            if (result != -1)
            {
                DispatchMessage(&msg);
            }
        }
    }

    不得不说的是,这些示例和我原来在网上和书上看到的很不一样,感觉他写的更加优雅,通过他的讲解,可以很容易理解。

    More content at http://pluralsight.com, Direct2D Fundamentals

  • 相关阅读:
    安卓内存不足(删除data/dalvik-cache目录)
    Blend Tree Type
    Unity 物理引擎动力学关节
    Daikon Forge GUI 制作图集和字体集
    Daikon Forge GUI 制作UI面板
    Vector3.Dot 判断方位
    (译)关于使用Eclipse Memory Analyzer的10点小技巧
    Android中Handler引起的内存泄露
    关于Android内存优化你应该知道的一切
    Android性能优化第(三)篇---MAT比Menmery Monitor更强大
  • 原文地址:https://www.cnblogs.com/sdflysha/p/3028212.html
Copyright © 2011-2022 走看看