前提・実現したいこと
ウィンドウのメインループを利用しているときにキューの割り込みをさせたい?ときはPostMessage
ではなくSendMessage
を使うと思いますが以下のコードのような別スレッドでキューの割り込みをさせるにはどうすればいいのでしょうか?("SendThreadMessage"などというものはないですし)
また別スレッドのキューが自身のキューにメッセージを投げるときPostThreadMessage
を使い第一引数のスレッド識別子はグローバル定義するしかないのでしょうか?
別スレッド内でWGLの描画を60fps(16ms)おきにWM_TIMER
を受け取って行うコードです.以下ではWM_TIMER
が来た時に再描画でTM_PAINT
を呼ぶためgoto文をとりあえず使っています.
該当のソースコード
C
1//main.cpp 2#define UNICODE 3 4#include <windows.h> 5#include <process.h> 6#include "GLLoop.h" 7 8LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 9 10const wchar_t CLASS_NAME[] = L"CLASS"; 11 12int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdLine, int nCmdShow) { 13 UNREFERENCED_PARAMETER(hPrevInstance); 14 UNREFERENCED_PARAMETER(nCmdLine); 15 16 WNDCLASSEX wc = { 17 sizeof(WNDCLASSEX),CS_VREDRAW | CS_HREDRAW, WindowProc, 18 0, 0, hInstance, 19 NULL, (HCURSOR)LoadCursor(NULL,IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 20 NULL, CLASS_NAME, NULL 21 }; 22 23 RegisterClassEx(&wc); 24 25 HWND hwnd = CreateWindowEx( 26 WS_EX_LAYERED, CLASS_NAME, L"Template", WS_OVERLAPPEDWINDOW, 27 50, 50, 960, 525, 28 NULL, NULL, hInstance, NULL 29 ); 30 SetLayeredWindowAttributes(hwnd, 0x0, 0, LWA_COLORKEY); 31 32 ShowWindow(hwnd, nCmdShow); 33 UpdateWindow(hwnd); 34 35 MSG msg = {}; 36 37 while (GetMessage(&msg, NULL, 0, 0) != 0) { 38 TranslateMessage(&msg); 39 DispatchMessage(&msg); 40 } 41 42 return (int)msg.wParam; 43} 44 45LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 46 static unsigned thId; 47 static RECT rc; 48 static HANDLE ht; 49 switch (uMsg) { 50 case WM_ERASEBKGND: 51 return -1; 52 53 case WM_CREATE: 54 { 55 static PassHandle mph; 56 mph.hwnd = hwnd; 57 ht = (HANDLE)_beginthreadex(NULL, 0, (_beginthreadex_proc_type)GLLoop, &mph, 0, &thId); 58 59 DWORD dwExCode; 60 while (GetExitCodeThread(ht, &dwExCode) && dwExCode == STILL_ACTIVE && !PostThreadMessage(thId, WM_NULL, 0, 0))Sleep(1); 61 62 PostThreadMessage(thId, TM_CREATE, 0, 0); 63 } 64 break; 65 66 case WM_PAINT: 67 { 68 PostThreadMessage(thId, TM_PAINT, 0, 0); 69 PAINTSTRUCT ps = {}; 70 BeginPaint(hwnd, &ps); 71 EndPaint(hwnd, &ps); 72 } 73 break; 74 75 case WM_SIZE: 76 { 77 GetClientRect(hwnd, &rc); 78 PostThreadMessage(thId, TM_SIZE, 0, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top)); 79 } 80 break; 81 82 case WM_DESTROY: 83 { 84 PostThreadMessage(thId, TM_DESTROY, 0, 0); 85 WaitForSingleObject(ht, INFINITE); 86 PostQuitMessage(0); 87 } 88 return 0; 89 } 90 91 return DefWindowProc(hwnd, uMsg, wParam, lParam); 92}
C
1//GLLoop.h 2#pragma once 3 4#pragma comment(lib,"opengl32.lib") 5#pragma comment(lib,"glu32.lib") 6 7#include <Windows.h> 8#include <windowsx.h> 9#include <process.h> 10#include <gl/GL.h> 11#include <gl/GLU.h> 12 13#define TM_CREATE WM_APP + WM_CREATE 14#define TM_DESTROY WM_APP + WM_DESTROY 15#define TM_SIZE WM_APP + WM_SIZE 16#define TM_PAINT WM_APP + WM_PAINT 17 18typedef struct _tagPassHandle{ 19 HWND hwnd; 20}PassHandle; 21 22DWORD WINAPI GLLoop(LPDWORD lpdata);
C
1//GLLoop.cpp 2#ifndef UNICODE 3#define UNICODE 4#endif UNICODE 5 6#include "GLLoop.h" 7 8HWND thwnd; 9 10HDC hdc; 11HGLRC glrc; 12int tWidth; 13int tHeight; 14 15GLfloat radius = 0; 16GLfloat latitude, longitude, latinc, longinc; 17 18DWORD WINAPI GLLoop(LPDWORD lpdata) { 19 20 PassHandle *ph = (PassHandle *)lpdata; 21 22 thwnd = ph->hwnd; 23 24 MSG tMsg = {}; 25 while (GetMessage(&tMsg, NULL, 0, 0) > 0) { 26 switch (tMsg.message) { 27 case TM_CREATE: 28 { 29 hdc = GetDC(thwnd); 30 31 PIXELFORMATDESCRIPTOR pfd = { 32 sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_COLORINDEX, 33 8, 34 0, 0, 0, 0, 0, 0, 0, 0, 35 0, 36 0, 0, 0, 0, 37 16, 0, 0, 0, 0, 38 0, 0, 0 39 }; 40 41 int format = ChoosePixelFormat(hdc, &pfd); 42 43 if (format == 0) { 44 MessageBox(thwnd, L"Failed to ChoosePixxelFormat", L"CAUTION", MB_OK); 45 break; 46 } 47 48 if (SetPixelFormat(hdc, format, &pfd) == FALSE) { 49 MessageBox(thwnd, L"Failed to SetPixxelFormat", L"CAUTION", MB_OK); 50 break; 51 } 52 53 glrc = wglCreateContext(hdc); 54 55 if (glrc == NULL) { 56 MessageBox(thwnd, L"Failed to wglCreateContext", L"CAUTION", MB_OK); 57 break; 58 } 59 60 wglMakeCurrent(hdc, glrc); 61 62 63 glClearIndex((GLfloat)0); 64 65 glClearDepth(1.0); 66 67 glEnable(GL_DEPTH_TEST); 68 69 glMatrixMode(GL_PROJECTION); 70 71 GLfloat aspect = (GLfloat)tWidth / tHeight; 72 73 gluPerspective(45.0, aspect, 3.0, 7.0); 74 75 glMatrixMode(GL_MODELVIEW); 76 77 radius = 3.0 + 7.0 / 2.0; 78 79 80 latitude = 0; 81 longitude = 5.0; 82 latinc = 0.5; 83 longitude = 0; 84 85 SetTimer(NULL, 1, 16, 0); 86 } 87 break; 88 89 case TM_PAINT: 90 { 91 redraw: 92 93 GLUquadricObj *quadObj; 94 95 glNewList(1, GL_COMPILE); 96 97 quadObj = gluNewQuadric(); 98 99 gluQuadricDrawStyle(quadObj, GLU_LINE); 100 101 gluSphere(quadObj, 1.5, 16, 16); 102 103 glEndList(); 104 105 106 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 107 108 glPushMatrix(); 109 110 glTranslated(0.0, 0.0, -radius); 111 glRotated(0, 0.0, 0.0, 1.0); 112 glRotated(-latitude, 1.0, 0.0, 0.0); 113 glRotated(longitude, 0.0, 0.0, 1.0); 114 115 glIndexi(13); 116 glCallList(3); 117 118 glIndexi(16); 119 glCallList(1); 120 121 glIndexi(14); 122 glPushMatrix(); 123 glTranslatef(0.8f, -0.65F, .0f); 124 glRotatef(30.0f, 1.0f, 0.5f, 1.0f); 125 glCallList(2); 126 glPopMatrix(); 127 glPopMatrix(); 128 129 SwapBuffers(hdc); 130 } 131 break; 132 133 case TM_SIZE: 134 { 135 tWidth = GET_X_LPARAM(tMsg.lParam); 136 tHeight = GET_Y_LPARAM(tMsg.lParam); 137 138 glViewport(0, 0, tWidth, tHeight); 139 140 GLfloat aspect = (GLfloat)tWidth / tHeight; 141 142 glMatrixMode(GL_PROJECTION); 143 glLoadIdentity(); 144 gluPerspective(45.0, aspect, 3.0, 7.0); 145 glMatrixMode(GL_MODELVIEW); 146 147 } 148 break; 149 150 case WM_TIMER: 151 { 152 latitude += latinc; 153 longitude += longinc; 154 155 goto redraw; 156 } 157 break; 158 159 case TM_DESTROY: 160 { 161 wglDeleteContext(glrc); 162 ReleaseDC(thwnd, hdc); 163 164 _endthreadex(0); 165 } 166 break; 167 } 168 } 169 170 return 0; 171}
補足情報
Windows10 Pro
VisualStudio2017 Community
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。