directX和windows api控件混合编程

本文介绍了如何在DirectX窗口中整合标准编辑框以实现文本输入功能,解决DirectX中缺乏自带控件的问题。通过创建两个窗口类,一个用于编辑框,一个用于DirectX渲染,作者成功地实现了这一需求。文中详细阐述了窗口创建、初始化Direct3D、文本框事件处理等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        由于奇形怪状的要求,需要在directX窗口中绘制一个可编辑的文本框。由于用dx中没有自带的控件,所以像这样的控件从渲染到回调都必须自己去写,并且如果想让他支持输入法和中文就更加困难,对于这个小项目来说就显得头重脚轻了。所以我就算是投机取巧,创建了两个windows窗口,一个窗口类名为edit,也就是标准的编辑框,另外一个窗口用dx渲染,成功解决了问题。

具体代码如下:

#include <windows.h>
#include<d3d9.h>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")        

#define ID_EDIT     1
#define WINDOW_CLASS "UGPDX"
#define WINDOW_NAME  "Drawing Lines"

// Function Prototypes...
bool InitializeD3D(HWND hWnd, bool fullscreen);
bool InitializeObjects();
void RenderScene();
void Shutdown();        

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM);       
// Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;

// Vertex buffer to hold the geometry.
LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;


// A structure for our custom vertex type
struct stD3DVertex
{
    float x, y, z, rhw;
    unsigned long color;
};
TCHAR szAppName[] = TEXT ("PopPad1") ;
// Our custom FVF, which describes our custom vertex structure.
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)        

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                   PSTR szCmdLine, int iCmdShow)
        
{
        
           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 ;
        
           }
		   wndclass.lpfnWndProc = ChildWndProc;
		   wndclass.cbWndExtra =sizeof(long);
		   wndclass.hIcon = NULL;
		   wndclass.lpszClassName = szChildClass;
		   RegisterClass (&wndclass);

    hwnd = CreateWindow (szAppName, szAppName,
        
                       WS_OVERLAPPEDWINDOW,
        
                       CW_USEDEFAULT, CW_USEDEFAULT,
        
                       CW_USEDEFAULT, CW_USEDEFAULT,
        
                       NULL, NULL, hInstance, NULL) ;
        
  ShowWindow (hwnd, iCmdShow) ;
        
  UpdateWindow (hwnd) ;
        
   
			ZeroMemory(&msg,sizeof(msg));
			while (msg.message!=WM_QUIT)
        
           {
				  if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
                  
				  {
					  if(msg.hwnd == GetDlgItem(hwnd,ID_EDIT) && msg.message == WM_KEYDOWN)
					  {
						  if(msg.wParam == VK_RETURN)
							  // 地址栏相应回车
					  }
				  }
				  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
		   else if(g_D3DDevice != NULL)
		   {
				RenderScene();	
		   }
		   // Release any and all resources.
   Shutdown();

   // Unregister our window.
   UnregisterClass(WINDOW_CLASS, wc.hInstance);
           return msg.wParam ;
        
}
        

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static HWND hwndChild,hwndEdit ;
        
           switch (message)
        
           {
        
           case   WM_CREATE :
        
                  hwndEdit = CreateWindow (TEXT ("edit"), NULL,
        
               WS_CHILD | WS_VISIBLE  | 
               WS_BORDER |
               ES_AUTOHSCROLL,
        
               0, 0, 0, 0, hwnd, (HMENU) ID_EDIT,
        
               (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL) ;

				  hwndChild = CreateWindow (szChildClass, NULL,
        
               WS_CHILDWINDOW | WS_VISIBLE  ,
        
               0, 50, 640, 480, hwnd, (HMENU) 101,
        
               (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL) ;
        
                  return 0 ;
				InistializeD3D(hwndChild,false);
        
        
           case   WM_SETFOCUS :
        
                  SetFocus (hwndEdit) ;
        
                  return 0 ;
        
        
        
           case   WM_SIZE :
        
           MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), 25, TRUE) ;
		   MoveWindow (hwndChild, 0, 25, LOWORD (lParam), HIWORD(lParam), TRUE) ;
        
                  return 0 ;
        
        
        
          
        
             
        
           case   WM_DESTROY :
        
                  PostQuitMessage (0) ;
        
                  return 0 ;
        
          }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}

LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM)
{
	switch(message)
	{
	
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}


bool InitializeD3D(HWND hWnd, bool fullscreen)
{
   D3DDISPLAYMODE displayMode;

   // Create the D3D object.
   g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
   if(g_D3D == NULL) return false;


   // Get the desktop display mode.
   if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
      &displayMode))) return false;


   // Set up the structure used to create the D3DDevice
   D3DPRESENT_PARAMETERS d3dpp;
   ZeroMemory(&d3dpp, sizeof(d3dpp));


   if(fullscreen)
      {
         d3dpp.Windowed = FALSE;
         d3dpp.BackBufferWidth = 640;
         d3dpp.BackBufferHeight = 480;
      }
   else
      d3dpp.Windowed = TRUE;
   d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
   d3dpp.BackBufferFormat = displayMode.Format;


   // Create the D3DDevice
   if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT,
      D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
      &d3dpp, &g_D3DDevice))) return false;


   // Initialize any objects we will be displaying.
   if(!InitializeObjects()) return false;

   return true;
}


bool InitializeObjects()
{
   unsigned long col = D3DCOLOR_XRGB(255, 255, 255);

   // Fill in our structure to draw an object.
   // x, y, z, rhw, color.
   stD3DVertex objData[] =
      {
         { 420.0f, 150.0f, 0.5f, 1.0f, col, },
         { 420.0f, 350.0f, 0.5f, 1.0f, col, },
         { 220.0f, 150.0f, 0.5f, 1.0f, col, },
         { 220.0f, 350.0f, 0.5f, 1.0f, col, },
      };

   // Create the vertex buffer.
   if(FAILED(g_D3DDevice->CreateVertexBuffer(sizeof(objData), 0,
             D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer,
             NULL))) return false;

   // Fill the vertex buffer.
   void *ptr;

   if(FAILED(g_VertexBuffer->Lock(0, sizeof(objData),
      (void**)&ptr, 0))) return false;

   memcpy(ptr, objData, sizeof(objData));

   g_VertexBuffer->Unlock();

   return true;
}


void RenderScene()
{
   // Clear the backbuffer.
   g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
                      D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

   // Begin the scene.  Start rendering.
   g_D3DDevice->BeginScene();

      // Render object.
      g_D3DDevice->SetStreamSource(0, g_VertexBuffer, 0,
                                   sizeof(stD3DVertex));
      g_D3DDevice->SetFVF(D3DFVF_VERTEX);
      g_D3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, 2);

   // End the scene.  Stop rendering.
   g_D3DDevice->EndScene();

   // Display the scene.
   g_D3DDevice->Present(NULL, NULL, NULL, NULL);
}


void Shutdown()
{
   if(g_D3DDevice != NULL) g_D3DDevice->Release();
   if(g_D3D != NULL) g_D3D->Release();
   if(g_VertexBuffer != NULL) g_VertexBuffer->Release();

   g_D3DDevice = NULL;
   g_D3D = NULL;
   g_VertexBuffer = NULL;
}
    在具体些程序中遇到不少问题,第一是如果将编辑框和dx绘制到一个窗口上,就会导致文本框闪烁。这是因为dx自动刷新的原因。第二是编辑框的回调是系统自己完成的,如果用setwindowlong函数改变回调的话,编辑框就会失效(回调都没了,也就没重绘了),虽然可以自己写,但也就失去了用编辑框的初衷了。所以采用的方法是直接在循环处理消息的时候回去该消息即:
while (msg.message!=WM_QUIT)
        
           {
				  if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
                  
				  {
					  if(msg.hwnd == GetDlgItem(hwnd,ID_EDIT) && msg.message == WM_KEYDOWN) //hwnd为主窗口句柄,ID_EDIT为编辑框编号
					  {
						  if(msg.wParam == VK_RETURN)
							  // 地址栏相应回车
					  }
				  }
				  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }

大致就是这些,如果想到问题在继续写。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值