skip to Main Content

Looking for the right general approach for making a UI really snappy.

I’m thinking of developing a UI tool that might go beyond just some “in house” tool. It would involve elaborate and custom 2d elements and would need to support fast scrolling of a big virtual surface, which would likely entail redrawing tons of custom things really quickly.

I’ve done some GDI programming back when XP was new, and I ran into some perf issues with lots of full screen blitting (it was a slow computer anyway). I understand GDI has some degree of acceleration, but I have difficulty ascertaining what exactly I can expect to be accelerated here.

I’ve only used Direct3D in games. Is it reasonable to make D3D to power a windowed GUI application? Also, if I use D3D, do I have to do everything from scratch, or can I make some kind of GDI/D3D hybrid, for example, using Direct3D calls inside WM_PAINT or something, in order to leverage some Win32 stuff like menu bars or listboxes side-by-side with a panel full of D3D rendered stuff? Does anyone have an example of mixing D3D with Win32 gui junk? Or is this not really the right approach?

What do programs like AutoCad or 3ds Max or Photoshop, or other major Win32 applications with similarly elaborate UI’s do?

2

Answers


  1. Simple C style D3D9 app code (display mesh).

    ////////////////////////////////////////////////////////////////
    // Defines main Direct3D rendering funcions
    
    
    #include <windows.h>
    #include <mmsystem.h>
    #include <d3d9.h>
    #include "d3dx9.h"
    #include "cube_prim.h"
    
    
    #ifndef __D3D_RENDERER_H__
    #define __D3D_RENDERER_H__
    
    
    #pragma comment(lib,"d3d9.lib")
    #pragma comment(lib,"d3dx9.lib")
    #pragma comment(lib,"winmm.lib")
    
    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
    
    LPDIRECT3D9 pDirect3D = NULL;
    LPDIRECT3DDEVICE9 pDirect3DDevice = NULL;
    LPDIRECT3DVERTEXBUFFER9 pDirect3DVertexBuffer = NULL;
    LPDIRECT3DINDEXBUFFER9 pDirect3DIndexBuffer = NULL;
    LPDIRECT3DTEXTURE9 pDirect3DTexture01 = NULL;
    LPDIRECT3DTEXTURE9 pDirect3DTexture02 = NULL;
    
    LPD3DXMESH pD3DXMesh = NULL;
    D3DMATERIAL9* pDirect3DMaterial = NULL;
    LPDIRECT3DTEXTURE9* pDirect3DTexture = NULL;
    DWORD Subsets = 0;
    
    FLOAT XRot = 0.0f;
    FLOAT YRot = 0.0f;
    
    
    HRESULT InitializeD3D(HWND hWnd)
    {
        D3DDISPLAYMODE dispMode;
        D3DPRESENT_PARAMETERS parameters;
    
        pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
    
        if (pDirect3D == NULL)
            return E_FAIL;
    
        if (FAILED(pDirect3D->GetAdapterDisplayMode(
            D3DADAPTER_DEFAULT,&dispMode)))
            return E_FAIL;
    
        ZeroMemory(&parameters,sizeof(D3DPRESENT_PARAMETERS));
        parameters.Windowed = FALSE;
        parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
        parameters.BackBufferFormat = dispMode.Format;
        parameters.BackBufferWidth = dispMode.Width;
        parameters.BackBufferHeight = dispMode.Height;
        parameters.BackBufferCount = 2;
        parameters.EnableAutoDepthStencil = TRUE;
        parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
    
    
        if (FAILED(pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,
            D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,
            &parameters,&pDirect3DDevice)))
            return E_FAIL;
    
        pDirect3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
        pDirect3DDevice->SetRenderState(D3DRS_AMBIENT,RGB(180,180,180));
        pDirect3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
        pDirect3DDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
        //pDirect3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_COLOR2);
        //pDirect3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_COLOR2);
        pDirect3DDevice->SetRenderState(D3DRS_SPECULARENABLE,TRUE);
    
        return S_OK;
    }
    
    
    HRESULT InitializeD3DBufferObject(void)
    {
        VOID* pVertices = NULL;
        VOID* pIndicies = NULL;
    
    
        if (pDirect3DDevice != NULL)
        {
            if (FAILED(pDirect3DDevice->CreateVertexBuffer(
                sizeof(vertices),0,D3DFVF_CUSTOMVERTEX,
                D3DPOOL_DEFAULT,&pDirect3DVertexBuffer,NULL)))
                return E_FAIL;
    
            if (FAILED(pDirect3DVertexBuffer->Lock(0,
                sizeof(vertices),(void**)&pVertices,NULL)))
                return E_FAIL;
    
            memcpy(pVertices,vertices,sizeof(vertices));
    
            pDirect3DVertexBuffer->Unlock();
    
            if (FAILED(pDirect3DDevice->CreateIndexBuffer(
                sizeof(indices),0,D3DFMT_INDEX32,D3DPOOL_DEFAULT,
                &pDirect3DIndexBuffer,NULL)))
                return E_FAIL;
    
            if (FAILED(pDirect3DIndexBuffer->Lock(0,
                sizeof(indices),(void**)&pIndicies,NULL)))
                return E_FAIL;
    
            memcpy(pIndicies,indices,sizeof(indices));
    
            pDirect3DIndexBuffer->Unlock();
    
            if (FAILED(D3DXCreateTextureFromFile(pDirect3DDevice,
                _T("wood.tga"),&pDirect3DTexture01)))
                return E_FAIL;
    
            if (FAILED(D3DXCreateTextureFromFile(pDirect3DDevice,
                _T("stripes.tga"),&pDirect3DTexture02)))
                return E_FAIL;
    
            return S_OK;
        }
        else
            return E_FAIL;
    }
    
    
    
    HRESULT InitialMesh(void)
    {
        LPD3DXBUFFER pMeshObj = NULL;
        LPD3DXMATERIAL pMaterial = NULL;
        char buffer[255];
    
        if (pDirect3DDevice != NULL)
        {
            if (FAILED(D3DXLoadMeshFromX(_T("Dwarf\Dwarf.x"),
                D3DXMESH_SYSTEMMEM,
                pDirect3DDevice,
                NULL,
                &pMeshObj,
                NULL,
                &Subsets,
                &pD3DXMesh)))
                return E_FAIL;
    
            pMaterial = (D3DXMATERIAL*)pMeshObj->GetBufferPointer();
    
            pDirect3DMaterial = new D3DMATERIAL9[Subsets];
            pDirect3DTexture = new LPDIRECT3DTEXTURE9[Subsets];
    
            for (INT i = 0; i < Subsets; i++)
            {
                pDirect3DMaterial[i] = pMaterial[i].MatD3D;
    
                sprintf(buffer,"Dwarf\");
                strcat(buffer,pMaterial[i].pTextureFilename);
    
                if (FAILED(D3DXCreateTextureFromFileA(
                    pDirect3DDevice,buffer,&pDirect3DTexture[i])))
                    return E_FAIL;
            }
    
            pMeshObj->Release();
    
            return S_OK;
        }
        else
            return E_FAIL;
    }
    
    
    
    VOID ChangeSize(INT cx,INT cy)
    {
        D3DXMATRIX projMatrix;
    
        if (pDirect3DDevice != NULL)
        {
            if (cy == 0)
                cy = 1;
    
            FLOAT aspectRatio = static_cast<FLOAT>(cx) / 
                static_cast<FLOAT>(cy);
    
            D3DXMatrixPerspectiveFovLH(&projMatrix,45.0f,
                aspectRatio,1.0f,150.0f);
    
            pDirect3DDevice->SetTransform(D3DTS_PROJECTION,&projMatrix);
        }
    }
    
    
    VOID RotateScene(void)
    {
        if (GetAsyncKeyState(VK_ESCAPE))
            exit(0);
    
        if (GetAsyncKeyState(VK_UP))
            XRot -= 0.1f;
    
        if (GetAsyncKeyState(VK_DOWN))
            XRot += 0.1f;
    
        if (GetAsyncKeyState(VK_LEFT))
            YRot -= 0.1f;
    
        if (GetAsyncKeyState(VK_RIGHT))
            YRot += 0.1f;
    }
    
    
    
    VOID RenderScene(void)
    {
        D3DXMATRIX worldMatrix;
        D3DMATERIAL9 material;
        D3DLIGHT9 light;
        D3DCAPS9 caps;
    
        D3DCOLORVALUE ambientLight = { 0.0f, 0.0f, 0.0f, 1.0f };
        D3DCOLORVALUE diffuseLight = { 0.7f, 0.7f, 0.7f, 1.0f };
        D3DCOLORVALUE specularLight = { 1.0f, 1.0f, 1.0f, 1.0f };
        D3DCOLORVALUE materialColor = { 1.0f, 1.0f, 1.0f, 1.0f };
    
        ZeroMemory(&material,sizeof(D3DMATERIAL9));
        material.Ambient = materialColor;
        material.Diffuse = materialColor;
        material.Specular = specularLight;
        material.Power = 20.0f;
    
        ZeroMemory(&light,sizeof(D3DLIGHT9));
        light.Ambient = ambientLight;
        light.Diffuse = diffuseLight;
        light.Specular = specularLight;
        light.Range = 300.0f;
        light.Position = D3DXVECTOR3(-30,150,-10);
        light.Type = D3DLIGHT_POINT;
        light.Attenuation0 = 1.0f;
    
        if (pDirect3DDevice != NULL)
        {
            D3DXMatrixIdentity(&worldMatrix);
            pDirect3DDevice->SetTransform(D3DTS_WORLD,&worldMatrix);
    
            D3DXMatrixTranslation(&worldMatrix,0.0f,0.0f,4.0f);
            pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
    
            D3DXMatrixRotationX(&worldMatrix,XRot);
            pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
    
            D3DXMatrixRotationY(&worldMatrix,YRot);
            pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
    
            pDirect3DDevice->Clear(0,0,D3DCLEAR_TARGET | 
                D3DCLEAR_ZBUFFER,D3DCOLOR_ARGB(255,0,0,0),1.0f,0);
    
            pDirect3DDevice->SetMaterial(&material);
            pDirect3DDevice->SetLight(0,&light);
            pDirect3DDevice->LightEnable(0,TRUE);
    
            pDirect3DDevice->SetTexture(0,pDirect3DTexture01);
            //pDirect3DDevice->SetTexture(1,pDirect3DTexture02);
    
            pDirect3DDevice->SetTextureStageState(0,
                D3DTSS_COLORARG1,D3DTA_TEXTURE);
            pDirect3DDevice->SetTextureStageState(0,
                D3DTSS_COLORARG2,D3DTA_DIFFUSE);
            pDirect3DDevice->SetTextureStageState(0,
                D3DTSS_COLOROP,D3DTOP_MODULATE);
    
            pDirect3DDevice->SetTextureStageState(1,
                D3DTSS_TEXCOORDINDEX,0);
            pDirect3DDevice->SetTextureStageState(1,
                D3DTSS_COLORARG1,D3DTA_TEXTURE);
            pDirect3DDevice->SetTextureStageState(1,
                D3DTSS_COLORARG1,D3DTA_TEXTURE);
            pDirect3DDevice->SetTextureStageState(1,
                D3DTSS_COLOROP,D3DTOP_MODULATE);
    
            pDirect3DDevice->GetDeviceCaps(&caps);
    
            pDirect3DDevice->SetSamplerState(0,D3DSAMP_MAXANISOTROPY,caps.MaxAnisotropy);
            pDirect3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
            pDirect3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
            pDirect3DDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_ANISOTROPIC);
    
            pDirect3DDevice->SetSamplerState(1,D3DSAMP_MAXANISOTROPY,caps.MaxAnisotropy);
            pDirect3DDevice->SetSamplerState(1,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
            pDirect3DDevice->SetSamplerState(1,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
            pDirect3DDevice->SetSamplerState(1,D3DSAMP_MIPFILTER,D3DTEXF_ANISOTROPIC);
    
            pDirect3DDevice->BeginScene();
            {
                pDirect3DDevice->SetStreamSource(0,pDirect3DVertexBuffer,0,
                    sizeof(CUSTOMVERTEX));
                pDirect3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
                pDirect3DDevice->SetIndices(pDirect3DIndexBuffer);
                /*pDirect3DDevice->DrawIndexedPrimitive(
                    D3DPT_TRIANGLELIST,0,0,36,0,12);*/
    
    
                for (int i = 0; i < Subsets; i++)
                {
                    pDirect3DDevice->SetMaterial(&pDirect3DMaterial[i]);
                    pDirect3DDevice->SetTexture(0,pDirect3DTexture[i]);
                    pD3DXMesh->DrawSubset(i);
                }
            }
            pDirect3DDevice->EndScene();
    
            pDirect3DDevice->Present(NULL,NULL,NULL,NULL);
        }
    }
    
    
    VOID ReleaseD3D(void)
    {
        if (pDirect3DTexture)
        {
            for (int i = 0; i < 0; i++)
                pDirect3DTexture[i]->Release();
        }
    
        if (pDirect3DMaterial)
        {
            delete [] pDirect3DMaterial;
        }
    
        if (pD3DXMesh)
            pD3DXMesh->Release();
    
        if (pDirect3DTexture02)
            pDirect3DTexture02->Release();
    
        if (pDirect3DTexture01)
            pDirect3DTexture01->Release();
    
        if (pDirect3DIndexBuffer)
            pDirect3DIndexBuffer->Release();
    
        if (pDirect3DVertexBuffer)
            pDirect3DVertexBuffer->Release();
    
        if (pDirect3DDevice)
            pDirect3DDevice->Release();
    
        if (pDirect3D)
            pDirect3D->Release();
    }
    
    #endif
    

    App use simple Win32 framework with WinMain etc…

    Sample code in MFC classes

    #include "MainWnd.h"
    #include "d3d_renderer.h"
    
    CMainWnd::CMainWnd(void)
    {
    }
    
    CMainWnd::~CMainWnd(void)
    {
    }
    BEGIN_MESSAGE_MAP(CMainWnd, CWnd)
        ON_WM_CREATE()
        ON_WM_DESTROY()
        ON_WM_SIZE()
        ON_WM_TIMER()
        ON_WM_PAINT()
    END_MESSAGE_MAP()
    
    // WM_CREATE
    int CMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
    
        if (FAILED(InitializeD3D(m_hWnd)))
            exit(0);
    
        if (FAILED(InitializeD3DBufferObject()))
            exit(0);
    
        if (FAILED(InitialMesh()))
            exit(0);
    
        SetTimer(33,1,NULL);
    
        return 0;
    }
    
    // WM_DESTROY
    void CMainWnd::OnDestroy()
    {
        CWnd::OnDestroy();
    
        KillTimer(101);
    
        ReleaseD3D();
    }
    
    // WM_SIZE
    void CMainWnd::OnSize(UINT nType, int cx, int cy)
    {
        CWnd::OnSize(nType, cx, cy);
    
        ChangeSize(cx,cy);
    }
    
    // WM_TIMER
    void CMainWnd::OnTimer(UINT_PTR nIDEvent)
    {
        InvalidateRect(NULL,FALSE);
    
        CWnd::OnTimer(nIDEvent);
    }
    
    // WM_PAINT
    void CMainWnd::OnPaint()
    {
        RotateScene();
    
        RenderScene();
    
        ValidateRect(NULL);
    }
    

    so decide what you want to use (D3D is significaly faster than GDI)

    you can also use OpenGL to draw accelerated graphics (little bit slower than D3D) with less code amount.

    Displaying 3D text with OpenGL and pure Win32 UI

    #include <windows.h>
    #include <glgl.h>
    #include <glglu.h>
    
    // Palette Handle
    HPALETTE hPalette = NULL;
    
    
    static LPCTSTR lpszAppName = "Text3D";
    GLint nFontList;
    
    // Light values and coordinates
    GLfloat  whiteLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
    GLfloat  diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
    GLfloat  specular[] = { 0.9f, 0.9f, 0.9f, 1.0f};
    GLfloat lightPos[] = { -100.0f, 200.0f, 50.0f, 1.0f };
    
    
    // Declaration for Window procedure
    LRESULT CALLBACK WndProc(   HWND    hWnd,
                                UINT    message,
                                WPARAM  wParam,
                                LPARAM  lParam);
    
    // Set Pixel Format function - forward declaration
    void SetDCPixelFormat(HDC hDC);
    
    
    
    void ChangeSize(GLsizei w, GLsizei h)
        {
        GLfloat nRange = 100.0f;
        GLfloat fAspect;
    
        // Prevent a divide by zero
        if(h == 0)
            h = 1;
    
        fAspect = (GLfloat)w/(GLfloat)h;
    
        // Set Viewport to window dimensions
        glViewport(0, 0, w, h);
    
        glMatrixMode(GL_PROJECTION);
    
        // Reset coordinate system
        glLoadIdentity();
    
        // Setup perspective for viewing
        gluPerspective(17.5f,fAspect,1,300);
    
        // Viewing transformation
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(-1.8f, 0.0f, -15.0f);
        glRotatef(-20.0f, 0.0f, 1.0f,0.0f);
    
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
        }
    
    
    void RenderScene(void)
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // Blue 3D Text
        glColor3ub(0, 0, 255);
    
        glPushMatrix();
        glListBase(nFontList);
        glCallLists (6, GL_UNSIGNED_BYTE, "OpenGL");    
        glPopMatrix();
        }
    
    
    void SetupRC(HDC hDC)
        {
        // Setup the Font characteristics
        HFONT hFont;
        GLYPHMETRICSFLOAT agmf[128]; // Throw away
        LOGFONT logfont;
    
        logfont.lfHeight = -10;
        logfont.lfWidth = 0;
        logfont.lfEscapement = 0;
        logfont.lfOrientation = 0;
        logfont.lfWeight = FW_BOLD;
        logfont.lfItalic = FALSE;
        logfont.lfUnderline = FALSE;
        logfont.lfStrikeOut = FALSE;
        logfont.lfCharSet = ANSI_CHARSET;
        logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
        logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
        logfont.lfQuality = DEFAULT_QUALITY;
        logfont.lfPitchAndFamily = DEFAULT_PITCH;
        strcpy(logfont.lfFaceName,"Arial");
    
        // Create the font and display list
        hFont = CreateFontIndirect(&logfont);
        SelectObject (hDC, hFont); 
    
    
        //create display lists for glyphs 0 through 128 with 0.1 extrusion 
        // and default deviation. 
        nFontList = glGenLists(128);
        wglUseFontOutlines(hDC, 0, 128, nFontList, 0.0f, 0.5f, 
                    WGL_FONT_POLYGONS, agmf); 
    
        DeleteObject(hFont);
    
        glEnable(GL_DEPTH_TEST);    // Hidden surface removal
        glEnable(GL_COLOR_MATERIAL);
    
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
    
        glEnable(GL_LIGHTING);
        glLightfv(GL_LIGHT0,GL_AMBIENT,whiteLight);
        glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
        glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
        glEnable(GL_LIGHT0);
    
    
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
        glMaterialfv(GL_FRONT, GL_SPECULAR,specular);
        glMateriali(GL_FRONT,GL_SHININESS,128);
        }
    
    
    // If necessary, creates a 3-3-2 palette for the device context listed.
    HPALETTE GetOpenGLPalette(HDC hDC)
        {
        HPALETTE hRetPal = NULL;    // Handle to palette to be created
        PIXELFORMATDESCRIPTOR pfd;  // Pixel Format Descriptor
        LOGPALETTE *pPal;           // Pointer to memory for logical palette
        int nPixelFormat;           // Pixel format index
        int nColors;                // Number of entries in palette
        int i;                      // Counting variable
        BYTE RedRange,GreenRange,BlueRange;
                                    // Range for each color entry (7,7,and 3)
    
    
        // Get the pixel format index and retrieve the pixel format description
        nPixelFormat = GetPixelFormat(hDC);
        DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    
        // Does this pixel format require a palette?  If not, do not create a
        // palette and just return NULL
        if(!(pfd.dwFlags & PFD_NEED_PALETTE))
            return NULL;
    
        // Number of entries in palette.  8 bits yeilds 256 entries
        nColors = 1 << pfd.cColorBits;  
    
        // Allocate space for a logical palette structure plus all the palette entries
        pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY));
    
        // Fill in palette header 
        pPal->palVersion = 0x300;       // Windows 3.0
        pPal->palNumEntries = nColors; // table size
    
        // Build mask of all 1's.  This creates a number represented by having
        // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
        // pfd.cBlueBits.  
        RedRange = (1 << pfd.cRedBits) -1;
        GreenRange = (1 << pfd.cGreenBits) - 1;
        BlueRange = (1 << pfd.cBlueBits) -1;
    
        // Loop through all the palette entries
        for(i = 0; i < nColors; i++)
            {
            // Fill in the 8-bit equivalents for each component
            pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
            pPal->palPalEntry[i].peRed = (unsigned char)(
                (double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
    
            pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
            pPal->palPalEntry[i].peGreen = (unsigned char)(
                (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);
    
            pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
            pPal->palPalEntry[i].peBlue = (unsigned char)(
                (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);
    
            pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
            }
    
    
        // Create the palette
        hRetPal = CreatePalette(pPal);
    
        // Go ahead and select and realize the palette for this device context
        SelectPalette(hDC,hRetPal,FALSE);
        RealizePalette(hDC);
    
        // Free the memory used for the logical palette structure
        free(pPal);
    
        // Return the handle to the new palette
        return hRetPal;
        }
    
    
    // Select the pixel format for a given device context
    void SetDCPixelFormat(HDC hDC)
        {
        int nPixelFormat;
    
        static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR),  // Size of this structure
            1,                              // Version of this structure    
            PFD_DRAW_TO_WINDOW |            // Draw to Window (not to bitmap)
            PFD_SUPPORT_OPENGL |            // Support OpenGL calls in window
            PFD_DOUBLEBUFFER,               // Double buffered mode
            PFD_TYPE_RGBA,                  // RGBA Color mode
            32,                             // Want 32 bit color
            0,0,0,0,0,0,                    // Not used to select mode
            0,0,                            // Not used to select mode
            0,0,0,0,0,                      // Not used to select mode
            16,                             // Size of depth buffer
            0,                              // Not used to select mode
            0,                              // Not used to select mode
            0,                              // Draw in main plane
            0,                              // Not used to select mode
            0,0,0 };                        // Not used to select mode
    
        // Choose a pixel format that best matches that described in pfd
        nPixelFormat = ChoosePixelFormat(hDC, &pfd);
    
        // Set the pixel format for the device context
        SetPixelFormat(hDC, nPixelFormat, &pfd);
        }
    
    
    
    // Entry point of all Windows programs
    int APIENTRY WinMain(   HINSTANCE   hInstance,
                            HINSTANCE   hPrevInstance,
                            LPSTR       lpCmdLine,
                            int         nCmdShow)
        {
        MSG         msg;        // Windows message structure
        WNDCLASS    wc;         // Windows class structure
        HWND        hWnd;       // Storeage for window handle
    
    
        // Register Window style
        wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wc.lpfnWndProc      = (WNDPROC) WndProc;
        wc.cbClsExtra       = 0;
        wc.cbWndExtra       = 0;
        wc.hInstance        = hInstance;
        wc.hIcon            = NULL;
        wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
    
        // No need for background brush for OpenGL window
        wc.hbrBackground    = NULL;     
    
        wc.lpszMenuName     = NULL;
        wc.lpszClassName    = lpszAppName;
    
        // Register the window class
        if(RegisterClass(&wc) == 0)
            return FALSE;
    
    
        // Create the main application window
        hWnd = CreateWindow(
                    lpszAppName,
                    lpszAppName,
    
                    // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS
                    WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
    
                    // Window position and size
                    100, 100,
                    250, 250,
                    NULL,
                    NULL,
                    hInstance,
                    NULL);
    
        // If window was not created, quit
        if(hWnd == NULL)
            return FALSE;
    
    
        // Display the window
        ShowWindow(hWnd,SW_SHOW);
        UpdateWindow(hWnd);
    
        // Process application messages until the application closes
        while( GetMessage(&msg, NULL, 0, 0))
            {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            }
    
        return msg.wParam;
        }
    
    
    
    // Window procedure, handles all messages for this program
    LRESULT CALLBACK WndProc(   HWND    hWnd,
                                UINT    message,
                                WPARAM  wParam,
                                LPARAM  lParam)
        {
        static HGLRC hRC;       // Permenant Rendering context
        static HDC hDC;         // Private GDI Device context
    
        switch (message)
            {
            // Window creation, setup for OpenGL
            case WM_CREATE:
                // Store the device context
                hDC = GetDC(hWnd);      
    
                // Select the pixel format
                SetDCPixelFormat(hDC);      
    
                // Create the rendering context and make it current
                hRC = wglCreateContext(hDC);
                wglMakeCurrent(hDC, hRC);
    
                // Create the palette
                hPalette = GetOpenGLPalette(hDC);
    
                SetupRC(hDC);
    
                break;
    
            // Window is being destroyed, cleanup
            case WM_DESTROY:
                // Kill the timer that we created
                KillTimer(hWnd,101);
    
                glDeleteLists(nFontList, 128);
    
                // Deselect the current rendering context and delete it
                wglMakeCurrent(hDC,NULL);
                wglDeleteContext(hRC);
    
                // Delete the palette
                if(hPalette != NULL)
                    DeleteObject(hPalette);
    
                // Tell the application to terminate after the window
                // is gone.
                PostQuitMessage(0);
                break;
    
            // Window is resized.
            case WM_SIZE:
                // Call our function which modifies the clipping
                // volume and viewport
                ChangeSize(LOWORD(lParam), HIWORD(lParam));
                break;
    
            // The painting function.  This message sent by Windows 
            // whenever the screen needs updating.
            case WM_PAINT:
                {
                // Call OpenGL drawing code
                RenderScene();
    
                // Call function to swap the buffers
                SwapBuffers(hDC);
    
                ValidateRect(hWnd,NULL);
                }
                break;
    
    
            // Windows is telling the application that it may modify
            // the system palette.  This message in essance asks the 
            // application for a new palette.
            case WM_QUERYNEWPALETTE:
                // If the palette was created.
                if(hPalette)
                    {
                    int nRet;
    
                    // Selects the palette into the current device context
                    SelectPalette(hDC, hPalette, FALSE);
    
                    // Map entries from the currently selected palette to
                    // the system palette.  The return value is the number 
                    // of palette entries modified.
                    nRet = RealizePalette(hDC);
    
                    // Repaint, forces remap of palette in current window
                    InvalidateRect(hWnd,NULL,FALSE);
    
                    return nRet;
                    }
                break;
    
    
            // This window may set the palette, even though it is not the 
            // currently active window.
            case WM_PALETTECHANGED:
                // Don't do anything if the palette does not exist, or if
                // this is the window that changed the palette.
                if((hPalette != NULL) && ((HWND)wParam != hWnd))
                    {
                    // Select the palette into the device context
                    SelectPalette(hDC,hPalette,FALSE);
    
                    // Map entries to system palette
                    RealizePalette(hDC);
    
                    // Remap the current colors to the newly realized palette
                    UpdateColors(hDC);
                    return 0;
                    }
                break;
    
    
            default:   // Passes it on if unproccessed
                return (DefWindowProc(hWnd, message, wParam, lParam));
    
            }
    
        return (0L);
        }
    

    can work without reseting palette

    AS window handle you may use every legal window handles (panel, listbox, buttons etc…) so you can display 3d content almost everywhere

    Photoshop use OpenGL, 3DS Max optional (OpenGL, Direct3D), AutoCad it is hard to say: GDI older versions, newest using .NET too.

    Login or Signup to reply.
  2. If your GUI involves 3D manipulation of 3D scenes, Direct3D or OpenGL would probably be a win. If you are just trying to give your GUI a “non-boring” look where the controls are stylized and drawn with alpha blended bitmaps and so-on, then you’re best sticking to the traditional windowing system (i.e. GDI) as the bottom-most rendering layer. However, the easiest way to achieve such a “look and feel” is to use a higher-level toolkit like wxWidgets or Qt in order to achieve the theming and customization that will make your GUI look “modern” and not like a boring corporate application.

    Another option is to use XAML/WPF from a native application and use the tools that are available for creating XAML-based GUIs like Microsoft’s Expression. I haven’t explored that myself, but it should be feasible using the technique from this article in the March, 2013 issue of MSDN Magazine.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search