右クリックで何度もウィンドウを生成したい。
Posted: 2012年4月16日(月) 08:52
開発環境はvc++2010 express,DXライブラリです。
右クリックを押してウィンドウを生成し
ウィンドウを閉じた後
もう一度生成することが出来ません。
TrackPopup関数を使っても処理が止まらないように
マルチスレッドを使っています。
ご助力の程、よろしくお願いします。
右クリックを押してウィンドウを生成し
ウィンドウを閉じた後
もう一度生成することが出来ません。
TrackPopup関数を使っても処理が止まらないように
マルチスレッドを使っています。
ご助力の程、よろしくお願いします。
//main.cpp
#include <windows.h>
#include <process.h>
#include <WindowsX.h>
#include "DxLib.h"
#include "dayData.h"
#include "draw_clock.h"
#include "Setup.h"
#include "resource.h"
#include <windowsx.h>
#define APP_NAME TEXT("clock")
#define chara_width 64
#define WM_POSTENDTHREAD (WM_USER)// スレッド終了を伝えるメッセージ
void jihou(struct dayData* day);
void plan(struct dayData* day);
void Time(struct dayData* day);
void date(struct dayData* day);
LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WindowProc2 (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
unsigned __stdcall mythread(void *lpx);
static HANDLE hThread;
static HWND hDlg[3];
static int chara_id;
HINSTANCE hInst,hInst2;
POINT pt;
struct dayData day[471];
unsigned __stdcall mythread(void *lpx){
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
// ウィンドウクラスの情報を設定
wc.cbSize = sizeof(wc); // 構造体サイズ
wc.style = CS_HREDRAW | CS_VREDRAW; // スタイル
wc.lpfnWndProc = WindowProc2; // ウィンドウプロシージャ
wc.cbClsExtra = 0; // 拡張情報1
wc.cbWndExtra = 0; // 拡張情報2
wc.hInstance = hInst; // インスタンスハンドル
wc.hIcon = (HICON)LoadImage( // アイコン
NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hIconSm = wc.hIcon; // 子アイコン
wc.hCursor = (HCURSOR)LoadImage( // マウスカーソル
NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景
wc.lpszMenuName = NULL; // メニュー名
wc.lpszClassName = _T("Default Class Name");// ウィンドウクラス名
// ウィンドウクラスを登録する
if( RegisterClassEx( &wc ) == 0 ){ return 1; }
// ウィンドウを作成する
hWnd = CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
_T("Sample Program"), // タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW, // ウィンドウの種類
CW_USEDEFAULT, // ウィンドウを表示する位置(X座標)
CW_USEDEFAULT, // ウィンドウを表示する位置(Y座標)
CW_USEDEFAULT, // ウィンドウの幅
CW_USEDEFAULT, // ウィンドウの高さ
NULL, // 親ウィンドウのウィンドウハンドル
NULL, // メニューハンドル
hInst2, // インスタンスハンドル
NULL // その他の作成データ
);
if( hWnd == NULL ){ return 1; }
// ウィンドウを表示する
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
while( 1 )
{
BOOL ret = GetMessage( &msg, NULL, 0, 0 ); // メッセージを取得する
if( ret == 0 || ret == -1 )
{
// アプリケーションを終了させるメッセージが来ていたら、
// あるいは GetMessage() が失敗したら( -1 が返されたら )、ループを抜ける
break;
}
else
{
// メッセージを処理する
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return 0;
}
LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static int top,left;
switch(uMsg) {
case WM_NCHITTEST:
return HTCAPTION;
case WM_LBUTTONDOWN:
{
// マウス状態管理用変数
int nClickNow = 0 , nClickPrev = 0;
// マウス状態の更新
nClickNow = (GetMouseInput() & MOUSE_INPUT_LEFT);
if( nClickNow != nClickPrev){
int MouseX = 0,MouseY = 0;
GetMousePoint( &MouseX , &MouseY ) ;// マウスの位置を取得
if(MouseX > chara_x && MouseX < chara_x + chara_width && MouseY > chara_y && MouseY < chara_y + chara_width ){
date(day);//日付を再生
Time(day);//時刻を再生
plan(day);
}
}
SendMessage(GetMainWindowHandle(), WM_NCLBUTTONDOWN, HTCAPTION, 0);//キャラクター画像の座標以外の時
// 今回のクリック状態を保持する
nClickPrev = nClickNow;
break;
}
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDM_OPTION:
if(!hDlg[0])hDlg[0] = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG), GetMainWindowHandle(), MyDlgProc);
break;
case IDM_EXIT:
Setup_save(day);//設定を書き込む
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
case IDM_VERSION:
if(!hDlg[1])hDlg[1] = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG2), GetMainWindowHandle(), MyDlgProc2);
break;
}
break;
case WM_RBUTTONDOWN:
if (hThread == NULL) {
hThread = (HANDLE)_beginthreadex(NULL, 0, mythread, NULL, 0, NULL);
}
break;
case WM_POSTENDTHREAD:
if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT) {
// まだスレッドが終了してなかったらメッセージを投げ直す
// ※デッドロック回避のため
PostMessage(hWnd, WM_POSTENDTHREAD, wParam, lParam);
}
else {
// スレッドの終了を検知できたら戻り値を取得してハンドルをクローズ
DWORD ExitCode;
ExitCode = -1;
GetExitCodeThread(hThread, &ExitCode);
CloseHandle(hThread);
hThread = NULL;
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
LRESULT CALLBACK WindowProc2 (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_RBUTTONDOWN:
HMENU hMenu,hSubMenu;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
hMenu = LoadMenu(hInst,"MYMENU");
hSubMenu = GetSubMenu(hMenu ,0);
ClientToScreen(GetMainWindowHandle() , &pt);
TrackPopupMenu(hSubMenu,TPM_LEFTALIGN,pt.x,pt.y,0,GetMainWindowHandle(),NULL);
DestroyMenu(hMenu);
break;
case WM_CLOSE:
PostMessage(GetMainWindowHandle(), WM_POSTENDTHREAD, 0, 0);// スレッド終了を伝えるメッセージを親ウィンドウに投げる
DestroyWindow(hWnd);
break;
default:
return ( DefWindowProc(hWnd , uMsg , wParam , lParam) );
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
// 画面モードの変更
SetGraphMode( 1680 , 1050 , 32 ) ;//パソコンの解像度に合わせる
SetMainWindowText("clock");
ChangeWindowMode( TRUE );
SetUseBackBufferTransColorFlag( TRUE );// ウインドウの透過色モードON
SetWindowStyleMode(2);
SetAlwaysRunFlag( TRUE );
SetHookWinProc( WindowProc );
if ( DxLib_Init( ) == -1 ) return -1;
SetDrawScreen(DX_SCREEN_BACK);
Load_Graph();
plan(day);//予定を音声再生する
while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
ClearDrawScreen( );
draw_face(day);
draw_clock(day);
jihou(day);//全ての描画関数が終わってから呼ぶ
ScreenFlip( );
}
DxLib_End();
return 0;
}