#include #include #include #include HWND hwnd; WNDCLASSEX the_wndclass; HINSTANCE the_hinstance; float app_scale_x, app_scale_y; IDirect3D9 *d3d_object; IDirect3DDevice9 *d3d_device; struct Line_Vertex { float x, y, z; unsigned long color; }; void draw_line(float x0, float y0, float x1, float y1, unsigned long color) { Line_Vertex vertices[2]; vertices[0].x = x0; vertices[0].y = y0; vertices[0].z = 0; vertices[0].color = color; vertices[1].x = x1; vertices[1].y = y1; vertices[1].z = 0; vertices[1].color = color; HRESULT hr = d3d_device->DrawPrimitiveUP(D3DPT_LINELIST, 1, vertices, sizeof(Line_Vertex)); } // // rendering_2d() sets the Direct3D transformation matrix for 2D rendering. // In an API geared toward 2D rendering you could probably just delete this function. // void rendering_2d(int width, int height) { D3DMATRIX m; memset(&m, 0, sizeof(D3DMATRIX)); m._11 = 2.0f * app_scale_x / (float)width; m._41 = -1.0f * app_scale_x; m._22 = 2.0f * app_scale_y / (float)height; m._42 = -1.0f * app_scale_y; m._33 = 1; m._43 = 0; m._34 = 0; m._44 = 1; d3d_device->SetTransform(D3DTS_PROJECTION, &m); } // Put points into a 4-element vertex buffer. void make_rectangle_points(Line_Vertex *p, float center_x, float center_y, float width, unsigned long color) { p[0].x = p[3].x = center_x - width; p[1].x = p[2].x = center_x + width; p[0].y = p[1].y = center_y - width; p[2].y = p[3].y = center_y + width; p[0].z = p[1].z = p[2].z = p[3].z = 0; p[0].color = p[1].color = p[2].color = p[3].color = color; } bool draw() { if (!d3d_device) return false; // Haven't been initialized yet! HRESULT result = d3d_device->BeginScene(); if (result != D3D_OK) return false; unsigned long clear_color = 0xffffffff; d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, clear_color, 1.0f, 0); d3d_device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE); d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); d3d_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); d3d_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); d3d_device->SetRenderState(D3DRS_LIGHTING, FALSE); RECT rect; GetClientRect(hwnd, &rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; rendering_2d(width, height); // Draw a grid background. unsigned long line_color = 0xffd0d0d0; for (int i = 0; i < width; i += 10) { draw_line(i, 0, i, height, line_color); } for (int j = 0; j < height; j += 10) { draw_line(0, j, width, j, line_color); } float center_x = width * 0.5f; float center_y = height * 0.5f; Line_Vertex p[5]; // Draw the solid rectangle. unsigned long solid_color = 0xff778899; make_rectangle_points(p, center_x, center_y, 50.0f, solid_color); result = d3d_device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, p, sizeof(Line_Vertex)); // Half the rectangle // Draw the outline rectangle. unsigned long outline_color = 0xffb0c7ee; make_rectangle_points(p, center_x, center_y, 100.0f, outline_color); p[4] = p[0]; // Make a closed loop. result = d3d_device->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, p, sizeof(Line_Vertex)); // Finish rendering; page flip. HRESULT hr = d3d_device->EndScene(); hr = d3d_device->Present(NULL, NULL, NULL, NULL); return true; } // Fill the struct that tells D3D how to set up buffers and page flip. void fill_out_present(D3DPRESENT_PARAMETERS *present, HWND hwnd) { RECT rect; GetClientRect(hwnd, &rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; ZeroMemory(present, sizeof(*present)); present->Windowed = TRUE; present->MultiSampleType = D3DMULTISAMPLE_NONE; present->SwapEffect = D3DSWAPEFFECT_DISCARD; present->EnableAutoDepthStencil = FALSE; present->BackBufferFormat = D3DFMT_A8R8G8B8; present->hDeviceWindow = hwnd; present->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; present->BackBufferCount = 1; present->BackBufferWidth = width; present->BackBufferHeight = height; present->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } /****************************************************************** * * * WndProc * * * * Window message handler * * * ******************************************************************/ LRESULT CALLBACK MessageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_PAINT: case WM_DISPLAYCHANGE: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); draw(); EndPaint(hwnd, &ps); } return 0; case WM_SIZE: { if (d3d_device) { D3DPRESENT_PARAMETERS present; fill_out_present(&present, hwnd); if (present.BackBufferWidth && present.BackBufferHeight) { d3d_device->Reset(&present); InvalidateRect(hwnd, NULL, FALSE); } } } break; case WM_DESTROY: { PostQuitMessage(0); } return 1; } return DefWindowProc( hwnd, message, wParam, lParam ); } /****************************************************************** * * * DemoApp::RunMessageLoop * * * * Main window message loop * * * ******************************************************************/ void run_message_loop() { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } void register_window_class(LPCWSTR winclass_name) { WNDCLASSEX wcl = { sizeof(WNDCLASSEX), CS_CLASSDC, MessageProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, (LPCWSTR)winclass_name, NULL }; the_wndclass = wcl; the_wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); int success = RegisterClassEx(&the_wndclass); assert(success); } bool initialize() { HRESULT hr; LPCWSTR name = _T("Not Using Direct2D"); register_window_class(name); // Get desktop DPI. HDC screen = GetDC(0); app_scale_x = (float)(GetDeviceCaps(screen, LOGPIXELSX) / 96.0); app_scale_y = (float)(GetDeviceCaps(screen, LOGPIXELSX) / 96.0); ReleaseDC(0, screen); int width = (int)(640 * app_scale_x); int height = (int)(480 * app_scale_y); hwnd = CreateWindow( name, name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, the_hinstance, NULL ); d3d_object = Direct3DCreate9(D3D_SDK_VERSION); // Fill out the presentation parameters for the D3D device... windowed mode. D3DPRESENT_PARAMETERS present; fill_out_present(&present, hwnd); UINT AdapterToUse = D3DADAPTER_DEFAULT; D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL; d3d_object->CreateDevice(AdapterToUse, DeviceType, hwnd, D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &d3d_device); if (!d3d_device) return false; ShowWindow(hwnd, SW_SHOWNORMAL); UpdateWindow(hwnd); return true; } /****************************************************************** * * * WinMain * * * * Application entrypoint * * * ******************************************************************/ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { the_hinstance = hInstance; initialize(); run_message_loop(); return 0; }