由于奇形怪状的要求,需要在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) ;
}
大致就是这些,如果想到问题在继续写。