質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

910閲覧

WinAPI 子スレッドでの描画

Weapon

総合スコア106

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2018/12/12 06:28

前提・実現したいこと

子ウィンドウでのOpenGLのループや子スレッドにおける子ウィンドウ作成について回答してまいりましたが今回子スレッドにおいてメインスレッドで作成したウィンドウの描画をしようとしましたがうまくいきません.
質問は

1)スレッドにどこまでを渡すべきか(HWNDのみ子スレッドに渡してデバイスコンテキストは子スレッドで取得 or HWND及びHDCを子スレッドに渡す)またはグローバル変数にしてしまうべきでしょうか.
2)_beginthreadexを以下の子ウィンドウWM_PAINTで呼ぶ場合ボトルネックで次の呼び出しが来てしまうためかメモリリークするためWM_CREATEで呼んでいますがどのようにすればいいのでしょうか.
3)描画されないのは何が問題でしょうか.

switch文等多くループする関数内での変数宣言がなれないところもあるので問題もありましたらご指摘ください.お願いします.

該当のソースコード

C

1//main 2 3#ifndef UNICODE 4#define UNICODE 5#endif UNICODE 6 7#include <windows.h> 8#include <process.h> 9#include "render thread.h" 10#include "Header.h" 11 12LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 13LRESULT CALLBACK ChildWindowProc(HWND, UINT, WPARAM, LPARAM); 14 15HINSTANCE hInst; 16 17RECT rc; 18HWND chwnd; 19 20const wchar_t CLASS_NAME[] = L"CLASS"; 21const wchar_t CHILD_CLASS_NAME[] = L"CHILD_CLASS"; 22 23int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdLine, int nCmdShow) { 24 UNREFERENCED_PARAMETER(hPrevInstance); 25 UNREFERENCED_PARAMETER(nCmdLine); 26 27 hInst = hInstance; 28 29 WNDCLASSEX wc = { 30 sizeof(WNDCLASSEX),CS_VREDRAW | CS_HREDRAW, WindowProc, 31 0, 0, hInstance, 32 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(GRAY_BRUSH), 33 NULL, CLASS_NAME, NULL 34 }; 35 36 RegisterClassEx(&wc); 37 38 HWND hwnd = CreateWindowEx( 39 0, CLASS_NAME, L"Template", WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN, 40 50, 50, 960, 525, 41 NULL, NULL, hInstance, NULL 42 ); 43 44 ShowWindow(hwnd, nCmdShow); 45 UpdateWindow(hwnd); 46 47 MSG msg = {}; 48 49 while (GetMessage(&msg, NULL, 0, 0)) { 50 TranslateMessage(&msg); 51 DispatchMessage(&msg); 52 } 53 54 return (int)msg.wParam; 55} 56 57LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 58 switch (uMsg) { 59 case WM_CREATE: 60 { 61 WNDCLASSEX wcx = { 62 sizeof(WNDCLASSEX),CS_VREDRAW | CS_HREDRAW, ChildWindowProc, 63 0, 0, hInst, 64 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH), 65 NULL, CHILD_CLASS_NAME, NULL 66 }; 67 68 RegisterClassEx(&wcx); 69 70 chwnd = CreateWindowEx( 71 0, CHILD_CLASS_NAME, L"", WS_CHILD|WS_VISIBLE|WS_THICKFRAME, 72 0, 0, 0, 0, 73 hwnd, NULL, hInst, NULL 74 ); 75 76 ShowWindow(chwnd, SW_SHOW); 77 UpdateWindow(chwnd); 78 } 79 break; 80 81 case WM_SIZE: 82 { 83 GetClientRect(hwnd, &rc); 84 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); 85 } 86 break; 87 88 case WM_PAINT: 89 { 90 } 91 break; 92 93 case WM_DESTROY: 94 PostQuitMessage(0); 95 return 0; 96 } 97 98 return DefWindowProc(hwnd, uMsg, wParam, lParam); 99} 100 101LRESULT CALLBACK ChildWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 102 switch (uMsg) { 103 static RENDTHDATA mrtd; 104 case WM_CREATE: 105 { 106 mrtd.hwnd = hwnd; 107 mrtd.hdc = GetDC(hwnd); 108 mrtd.size = (rc.right - rc.left) / 2 - 5; 109 110 wchar_t mess[1024] = { 0 }; 111 wsprintf(mess, L"HWND : %d\n HDC : %x\nSize : %d", mrtd.hwnd, mrtd.hdc, mrtd.size); 112 _beginthreadex(NULL, 0, (_beginthreadex_proc_type)render, &mrtd, 0, NULL); 113 114 } 115 break; 116 117 case WM_PAINT: 118 break; 119 120 case WM_DESTROY: 121 PostQuitMessage(0); 122 return 0; 123 } 124 125 DefWindowProc(hwnd, uMsg, wParam, lParam); 126}

C

1//Header.h 2#pragma once 3#include <windows.h> 4 5typedef struct _tagRENDTHDATA { 6 HWND hwnd; 7 HDC hdc; 8 int size; 9}RENDTHDATA; 10

C

1//render thread.h 2#pragma once 3#include <windows.h> 4 5DWORD WINAPI render(LPVOID);

C

1//render thread.cpp 2#define UNICODE 3#include <windows.h> 4#include "render thread.h" 5#include "Header.h" 6 7int width =10000; 8int height = 10000; 9 10DWORD WINAPI render(LPVOID lp) { 11 RENDTHDATA *rtd = (RENDTHDATA *)lp; 12 13 HWND hwnd = rtd->hwnd; 14 HDC hdc = rtd->hdc; 15 int size = rtd->size; 16 17 DWORD **image = (DWORD**)malloc(sizeof(DWORD*)*width); 18 DWORD *image_c = (DWORD*)malloc(sizeof(DWORD)*width*height); 19 for (int i = 0; i < width; i++)image[i] = image_c + i * height; 20 for (int i = 0; i < width; i++)for (int j = 0; j < height; j++)image[i][j] = 0x000000ff; 21 22 DWORD *dib = (DWORD*)calloc(width*height, sizeof(DWORD)); 23 24 // traca 25 for (int i = 0; i < width; i++)for (int j = 0; j < height; j++)dib[i + j * width] = image[height - j - 1][i]; 26 27 BITMAPINFO bmpi; 28 ZeroMemory(&bmpi, sizeof(bmpi)); 29 bmpi.bmiHeader.biSize = sizeof(bmpi); 30 bmpi.bmiHeader.biWidth = width; 31 bmpi.bmiHeader.biHeight = height; 32 bmpi.bmiHeader.biPlanes = 1; 33 bmpi.bmiHeader.biBitCount = 32; 34 bmpi.bmiHeader.biCompression = BI_RGB; 35 36 int a = StretchDIBits( 37 hdc, 0, 0, width, height, 0, 0, size, size, 38 dib, &bmpi, 39 DIB_RGB_COLORS, SRCCOPY 40 ); 41 42 InvalidateRect(hwnd, NULL, TRUE); 43 44 wchar_t mess3[1024] = { 0 }; 45 wsprintf(mess3, L"width : %d", size); 46 MessageBox(NULL, mess3, L"Alert", MB_OK); 47 48 free(dib); 49 free(image_c); 50 free(image); 51 52 return 0; 53}

補足情報

Windows10 Pro
VisualStudio2017 Community

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

とりあえず描画されていない理由について

int size = rtd->size;

領域が読み込まれていないため-5が設定されています。
CreateWindowで子ウィンドウ作る前にでも

c++

1GetClientRect(hwnd, &rc);

を入れておくこと

InvalidateRect(hwnd, NULL, TRUE);

これは、hwndを全部描画しなおせ という命令です。
結果、せっかく描画したのにその上から真っ白で描き直されてしまうので描画されていないように見えます


1,2については
なぜスレッドを作成してそちらで描写させる必要があるのか?という疑問に行き着きます。

私でしたら、CreateCompatibleDC等を用いて再描画用のビットマップを作って
WM_PAINT時は再描画用ビットマップから再描画が必要な領域を転送
画像に変化があるときはスレッドを起動し再描画用ビットマップを新たに作らせます。

まぁ、いわゆるダブルバッファ的なやつです

単純にスレッド作ってやらせると順番入れ替わってバグりそうなので
PostThreadMessageでキュー作ってメッセージループにするのもよさそうですね

投稿2018/12/12 13:03

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問