前提・実現したいこと
WinAPI 子スレッドでの描画でキューを作りメッセージループとご教授いただいたのですが子スレッドにおいてキューはどうやって取得するのでしょうか?
メインウィンドウの場合GetMessage
で取得してDispatchMessage
からWindowProc
にメッセージが渡っていたと思っていましたがこの場合のスレッドはウィンドウではないからWindowProc
ではないでしょうしスレッドの関数そのもののThreadProc
とも違いますよね.
どのようにメッセージループを実装すればいいのでしょうか?
またプロシージャ内のswitch
前,switch
下(case
前),グローバル宣言それぞれでstatic
で変数宣言することにどのような違いがあるのでしょう?
発生している問題・エラーメッセージ
C
1//main 2#ifndef UNICODE 3#define UNICODE 4#endif UNICODE 5 6#include <windows.h> 7#include <process.h> 8#include "render thread.h" 9#include "Header.h" 10 11LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 12LRESULT CALLBACK ChildWindowProc(HWND, UINT, WPARAM, LPARAM); 13 14HINSTANCE hInst; 15 16RECT rc; 17HWND chwnd; 18 19static unsigned thid; 20 21const wchar_t CLASS_NAME[] = L"CLASS"; 22const wchar_t CHILD_CLASS_NAME[] = L"CHILD_CLASS"; 23 24int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdLine, int nCmdShow) { 25 UNREFERENCED_PARAMETER(hPrevInstance); 26 UNREFERENCED_PARAMETER(nCmdLine); 27 28 hInst = hInstance; 29 30 WNDCLASSEX wc = { 31 sizeof(WNDCLASSEX),CS_VREDRAW | CS_HREDRAW, WindowProc, 32 0, 0, hInstance, 33 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(GRAY_BRUSH), 34 NULL, CLASS_NAME, NULL 35 }; 36 37 RegisterClassEx(&wc); 38 39 HWND hwnd = CreateWindowEx( 40 0, CLASS_NAME, L"Template", WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN, 41 50, 50, 960, 525, 42 NULL, NULL, hInstance, NULL 43 ); 44 45 ShowWindow(hwnd, nCmdShow); 46 UpdateWindow(hwnd); 47 48 MSG msg = {}; 49 50 while (GetMessage(&msg, NULL, 0, 0)) { 51 TranslateMessage(&msg); 52 DispatchMessage(&msg); 53 } 54 55 return (int)msg.wParam; 56} 57 58LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 59 switch (uMsg) { 60 case WM_CREATE: 61 { 62 WNDCLASSEX wcx = { 63 sizeof(WNDCLASSEX),CS_VREDRAW | CS_HREDRAW, ChildWindowProc, 64 0, 0, hInst, 65 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH), 66 NULL, CHILD_CLASS_NAME, NULL 67 }; 68 69 RegisterClassEx(&wcx); 70 71 chwnd = CreateWindowEx( 72 0, CHILD_CLASS_NAME, L"", WS_CHILD|WS_VISIBLE|WS_THICKFRAME, 73 0, 0, 0, 0, 74 hwnd, NULL, hInst, NULL 75 ); 76 77 ShowWindow(chwnd, SW_SHOW); 78 UpdateWindow(chwnd); 79 } 80 break; 81 82 case WM_SIZE: 83 { 84 GetClientRect(hwnd, &rc); 85 MoveWindow(chwnd, 5, (rc.bottom - rc.top - (rc.right - rc.left) / 2)/2, (rc.right - rc.left) / 2 - 5, (rc.right - rc.left) / 2 - 5, TRUE); 86 MoveWindow(form, (rc.right - rc.left) * 3 / 4 , 150, 100, 50, TRUE); 87 MoveWindow(button, (rc.right - rc.left) * 3 / 4 + 110, 150, 100, 50, TRUE); 88 } 89 break; 90 91 case WM_DESTROY: 92 PostQuitMessage(0); 93 return 0; 94 } 95 96 return DefWindowProc(hwnd, uMsg, wParam, lParam); 97} 98 99LRESULT CALLBACK ChildWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 100 switch (uMsg) { 101 static RENDTHDATA mrtd; 102 case WM_CREATE: 103 { 104 GetClientRect(GetParent(hwnd), &rc); 105 mrtd.hwnd = hwnd; 106 mrtd.hdc = GetDC(hwnd); 107 mrtd.size = (rc.right - rc.left) / 2 - 5; 108 109 wchar_t mess[1024] = { 0 }; 110 wsprintf(mess, L"HWND : %d\n HDC : %x\nSize : %d", mrtd.hwnd, mrtd.hdc, mrtd.size); 111 MessageBox(NULL, mess, L"Alert", MB_OK); 112 113 _beginthreadex(NULL, 0, (_beginthreadex_proc_type)render, &mrtd, 0, &thid); 114 PostThreadMessage(thid, WM_NULL, 0, 0); 115 116 } 117 break; 118 119 case WM_PAINT: 120 121 PostThreadMessage(thid, TM_PAINT, 0, 0); 122 break; 123 124 case WM_DESTROY: 125 PostThreadMessage(thid, TM_PAINT, 0, 0); 126 _endthreadex(0); 127 PostQuitMessage(0); 128 return 0; 129 } 130 131 DefWindowProc(hwnd, uMsg, wParam, lParam); 132}
C
1//Header.h 2#pragma once 3 4#include <windows.h> 5 6typedef struct _tagRENDTHDATA { 7 HWND hwnd; 8 HDC hdc; 9 int size; 10}RENDTHDATA; 11 12#define TM_CREATE (WM_APP+1) 13#define TM_DESTROY (WM_APP+2) 14#define TM_PAINT (WM_APP+3)
C
1//render thread.h 2#pragma once 3 4#define UNICODE 5#include <windows.h> 6 7DWORD WINAPI render(LPVOID);
C
1//render thread.cpp 2#define UNICODE 3 4#include <windows.h> 5#include "render thread.h" 6#include "Header.h" 7 8int width =10000; 9int height = 10000; 10 11DWORD WINAPI render(LPVOID lp) { 12 13 RENDTHDATA *rtd = (RENDTHDATA *)lp; 14 15 HWND hwnd = rtd->hwnd; 16 HDC hdc = rtd->hdc; 17 int size = rtd->size; 18 19 static MSG tMsg = {}; 20 21 while (GetMessage(&tMsg, hwnd, 0, 0)>0) { 22 switch (tMsg.message) { 23 static DWORD **image; 24 static DWORD *image_c; 25 static DWORD *dib; 26 static BITMAPINFO bmpi; 27 case TM_CREATE: 28 { 29 MessageBox(NULL, L"CALLED", L"Alert", MB_OK); 30 31 image = (DWORD**)malloc(sizeof(DWORD*)*width); 32 image_c = (DWORD*)malloc(sizeof(DWORD)*width*height); 33 for (int i = 0; i < width; i++)image[i] = image_c + i * height; 34 for (int i = 0; i < width; i++)for (int j = 0; j < height; j++)image[i][j] = 0x000000ff; 35 36 dib = (DWORD*)calloc(width*height, sizeof(DWORD)); 37 38 ZeroMemory(&bmpi, sizeof(bmpi)); 39 bmpi.bmiHeader.biSize = sizeof(bmpi); 40 bmpi.bmiHeader.biWidth = width; 41 bmpi.bmiHeader.biHeight = height; 42 bmpi.bmiHeader.biPlanes = 1; 43 bmpi.bmiHeader.biBitCount = 32; 44 bmpi.bmiHeader.biCompression = BI_RGB; 45 } 46 break; 47 48 case TM_PAINT: 49 { 50 for (int i = 0; i < width; i++)for (int j = 0; j < height; j++)dib[i + j * width] = image[height - j - 1][i]; 51 52 int a = StretchDIBits( 53 hdc, 0, 0, width, height, 0, 0, size, size, 54 dib, &bmpi, 55 DIB_RGB_COLORS, SRCCOPY 56 ); 57 } 58 break; 59 60 case TM_DESTROY: 61 { 62 free(dib); 63 free(image_c); 64 free(image); 65 } 66 break; 67 68 } 69 } 70 return 0; 71}
ちなみにMonte Carloの円周率導出を時間で徐々にプロットしていくというレンダリングのキャンバスを作ろうとしていました.
なおcase TM_PAINT
1行目で行われているのは非効率ながらxy座標をDIBの線型配列に変換するものです.時間おきにプロット命令を入れるのでこの処理はcase TM_CREATE
ではしませんでした.プロット処理を追加したときはTM_TIMEなどを作成してそこを介してダブルバッファリングを考えています.
補足情報
Windows10 Pro
VisualStudio2017 Community

回答1件
あなたの回答
tips
プレビュー