我目前正在为一个爱好项目重新学习C,我正在尝试使用direct2D图形构建一个简单的UI。使用DirectX in C处提供的说明,我能够成功打开一个空白窗口。由于我的UI只需要很少的矩形,我没有在该教程中使用Direct3D代码。相反,我试图使用Direct2D API绘制一个填充矩形,但它无法正常工作。我已经多次遍历每一行代码并尝试了很多东西,但却无法使其工作。下面是我完整的C文件。
在我的render()函数中,
ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor);
似乎有效,但FillRectangle无法正常工作。有人可以告诉,如何解决这个问题?
#include <windows.h>
#include <malloc.h>
#include <d2d1.h>
#pragma comment(lib, "d2d1.lib")
const int WIDTH = 400;
const int HEIGHT = 400;
typedef struct {
HWND hWnd;
BOOL bDone;
ID2D1Factory* direct2dFactory;
ID2D1HwndRenderTarget* renderTarget;
ID2D1SolidColorBrush* m_pLightSlateGrayBrush;
ID2D1SolidColorBrush* m_pCornflowerBlueBrush;
} WindowObject;
static LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static void FreeWindowObject(WindowObject *window);
HRESULT CreateDeviceIndependentResources(WindowObject *window)
{
HRESULT hr = S_OK;
ID2D1Factory* pFactory = NULL;
const D2D1_FACTORY_OPTIONS opts = { D2D1_DEBUG_LEVEL_INFORMATION };
// Create a Direct2D factory.
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
&IID_ID2D1Factory, &opts, (void**)&pFactory);
window->direct2dFactory = pFactory;
return hr;
}
HRESULT CreateDeviceResources(WindowObject *window)
{
HRESULT hr = S_OK;
if (!window->renderTarget)
{
RECT rc;
GetClientRect(window->hWnd, &rc);
D2D1_SIZE_U size;
size.width = rc.right - rc.left;
size.height = rc.bottom - rc.top;
D2D1_RENDER_TARGET_PROPERTIES renderProps;
D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderProps;
D2D1_PIXEL_FORMAT pixFmt = { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN };
renderProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
renderProps.pixelFormat = pixFmt;
renderProps.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
renderProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
renderProps.dpiX = renderProps.dpiY = 0.f;
hwndRenderProps.hwnd = window->hWnd;
hwndRenderProps.pixelSize = size;
hwndRenderProps.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
// Create a Direct2D render target.
if (FAILED(hr = ID2D1Factory_CreateHwndRenderTarget(window->direct2dFactory,
&renderProps, &hwndRenderProps, &window->renderTarget)))
{
OutputDebugStringA("Failed to create render target, err = %#x\n", hr);
return 0;
}
D2D1_COLOR_F redColor = { 51, 51, 255 };
if (SUCCEEDED(hr))
{
// Create a gray brush.
hr = ID2D1HwndRenderTarget_CreateSolidColorBrush(window->renderTarget,
&redColor, NULL, &window->m_pLightSlateGrayBrush);
}
}
return hr;
}
void DiscardDeviceResources(WindowObject *window)
{
ID2D1HwndRenderTarget_Release(window->renderTarget);
ID2D1Factory_Release(window->direct2dFactory);
//ID2D1HwndRenderTarget_Release(window->m_pCornflowerBlueBrush);
//ID2D1HwndRenderTarget_Release(window->m_pLightSlateGrayBrush);
}
static WindowObject *CreateWindowObject(HINSTANCE hInstance)
{
WindowObject *window;
// Allocate the window data and create the window.
window = malloc(sizeof(WindowObject));
ZeroMemory(window, sizeof(WindowObject));
HRESULT hr = CreateDeviceIndependentResources(window);
const char *name = "Simple";
int x, y, width, height;
RECT rect;
DWORD dwStyle = WS_VISIBLE | WS_OVERLAPPEDWINDOW;
DWORD dwExStyle = WS_EX_CLIENTEDGE;
WNDCLASS wndClass = {
CS_HREDRAW | CS_VREDRAW, WinProc, 0, 0, hInstance,
0, LoadCursor(0, IDC_ARROW),
1, 0, name
};
RegisterClass(&wndClass);
window->hWnd = CreateWindowEx(
dwExStyle, name, name, dwStyle,
CW_USEDEFAULT,
CW_USEDEFAULT, WIDTH, HEIGHT,
0, 0, hInstance, 0
);
SetWindowLongPtr(window->hWnd, GWLP_USERDATA, window);
hr = window->hWnd ? S_OK : E_FAIL;
return window;
}
HRESULT render(WindowObject *window)
{
HRESULT hr = S_OK;
hr = CreateDeviceResources(window);
if (!SUCCEEDED(hr))
{
return hr;
}
ID2D1HwndRenderTarget_BeginDraw(window->renderTarget);
D2D1_COLOR_F whiteColor = { 255, 255,255 };
ID2D1HwndRenderTarget_Clear(window->renderTarget, &whiteColor);
// Draw rectangle.
D2D1_RECT_F rectangle1 = { 10, 10,100,100 };
ID2D1HwndRenderTarget_FillRectangle(window->renderTarget, &rectangle1, window->m_pLightSlateGrayBrush);
hr = ID2D1HwndRenderTarget_EndDraw(window->renderTarget, NULL, NULL);
if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources(window);
}
return hr;
}
static LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WindowObject *window = (WindowObject *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (uMsg) {
case WM_KEYUP:
if (wParam == VK_ESCAPE)
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
case WM_PAINT:
render(window);
ValidateRect(hWnd, NULL);
return 0;
break;
case WM_CLOSE:
window->bDone = TRUE;
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WindowObject *window = CreateWindowObject(hInstance);
while (!window->bDone) {
MSG msg;
if (PeekMessage(&msg, window->hWnd, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
render(window);
ValidateRect(window->hWnd, NULL);
}
}
FreeWindowObject(window);
return 0;
}
static void FreeWindowObject(WindowObject *window)
{
DiscardDeviceResources(window);
free(window);
}
答案 0 :(得分:0)
D2D1_COLOR_F redColor = { 51, 51, 255, 255 };
请记住,D2D1_COLOR_F
是RGBA,而不是RGB。因此,这会初始化alpha值为0的颜色,这是完全透明的。如果你想要一个完全不透明的矩形,你需要说:
_F
除了仍然不正确之外,因为51.0/255.0
的字段是[0,1]范围内的浮点(51
)。所以你需要做的是替换1.0
代替255
而 D2D1_COLOR_F redColor = { 51.0 / 255.0, 51.0 / 255.0, 1.0, 1.0 };
代替typedef
:
yield
现在你的矩形应该出现了。
请务必阅读the documentation;它解释了一切(即使你必须点击一些Linq
才能到达那里)。