ページ 11

ダイアログプロシージャのコンボボックスの制御がうまくいかない。

Posted: 2012年3月27日(火) 03:56
by s707
現在デスクトップクロックを制作中です。

コンボボックスをクリックしてA→B→C→D→日本→A
という順番で表示させたいのですが

実行するとA→B→Dという順番で表示されてしまいます。


ダイアログボックスを表示中も時計を動かす為に
別のスレッドでダイアログボックスを作成しています。

原因が分からず詰まっています。
ご助力の程、よろしくお願い致します。

コード:

//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);
void version(struct dayData* day);
int  title(int,struct dayData* day);

unsigned __stdcall mythread(void *lpx);
LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK MyDlgProc(HWND hChild, UINT msg, WPARAM wp, LPARAM lp);


static HANDLE hThread[2];
static HWND hDlg[2],ComboBox;
static int chara_id;
HINSTANCE hInst;
POINT pt;
struct dayData day[471];

BOOL CALLBACK MyDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
	switch(msg) {
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case IDOK:
			PostQuitMessage(IDOK);
			return TRUE;
		case IDCANCEL:
			PostQuitMessage(IDCANCEL);
			return TRUE;
		case IDC_COMBO1:
			ComboBox_SetCurSel(ComboBox,chara_id++);
			chara_id %= 5;
			return TRUE;
		}
		return FALSE;
	case WM_INITDIALOG:
		return TRUE;
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	}
	return FALSE;
}

unsigned __stdcall mythread(void *lpx){
	MSG msg;

	char character[5][10] = {"A","B","C","D","日本"};

	hDlg[0] = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG), GetMainWindowHandle(), MyDlgProc);

	ComboBox = GetDlgItem( hDlg[0], IDC_COMBO1);

	for(int i = 0; i<5; i++){
		ComboBox_AddString(ComboBox,character[i]);
	}
	chara_id = (day + 4) -> number[0];
	ComboBox_SetCurSel(ComboBox,chara_id);

	ShowWindow(hDlg[0], SW_NORMAL);
	while (GetMessage(&msg, NULL, 0, 0)) {
		if (!IsDialogMessage(hDlg[0], &msg)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	(day + 4) -> number[0] = chara_id;

	Setup_save(day);//設定を書き込む


	// スレッド終了を伝えるメッセージを親ウィンドウに投げる
	PostMessage(GetMainWindowHandle(), WM_POSTENDTHREAD, 0, 0);
	return msg.wParam;
}

LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	static int top = 0;
	HMENU hMenu,hSubMenu;

	switch(uMsg) {
	case WM_MOVING:
		{		
			LPRECT p = (LPRECT)lParam;
			top = p -> top;
			break;
		}
	case WM_WINDOWPOSCHANGING:		
		{
			WINDOWPOS* p = (WINDOWPOS*)lParam;
			p -> y = top;
			break;
		}
	case WM_NCHITTEST:
		return HTCAPTION;
	case WM_LBUTTONDOWN:
		SendMessage(GetMainWindowHandle(), WM_NCLBUTTONDOWN, HTCAPTION, 0);
		break;
	case WM_RBUTTONDOWN:
		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_COMMAND:
		switch(LOWORD(wParam)){
		case IDM_OPTION:
			if (hThread[0] == NULL) {
				hThread[0] = (HANDLE)_beginthreadex(NULL, 0, mythread, NULL, 0, NULL);
			}
			break;
		case IDM_EXIT:
			SendMessage(hWnd, WM_CLOSE, 0, 0);
			break;
		}
		break;
	case WM_POSTENDTHREAD:
		for(int i = 0; i < 2; i++){
			if (WaitForSingleObject(hThread[i], 0) == WAIT_TIMEOUT) {
				// まだスレッドが終了してなかったらメッセージを投げ直す
				// ※デッドロック回避のため
				PostMessage(hWnd, WM_POSTENDTHREAD, wParam, lParam);
			}
			else {
				// スレッドの終了を検知できたら戻り値を取得してハンドルをクローズ
				DWORD ExitCode[2];
				ExitCode[i] = -1;
				GetExitCodeThread(hThread[i], &ExitCode[i]);
				CloseHandle(hThread[i]);
				hThread[i] = NULL;
			}
		}
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){

	// マウス状態管理用変数
	int nClickNow = 0 , nClickPrev = 0;
	int nClickNow_R = 0 , nClickPrev_R = 0;
	int nClickR_Count = 0;

	int status = 0,temp = 0;
	bool menu_flg = false;

	// 画面モードの変更
	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();
	Setup_load(day);//設定を読み込む
	plan(day);//予定を音声再生する	

	while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
		ClearDrawScreen( );
//処理を省略
		ScreenFlip( );
	}
	DxLib_End( );
	return 0;
}

Re: ダイアログプロシージャのコンボボックスの制御がうまくいかない。

Posted: 2012年3月27日(火) 12:31
by softya(ソフト屋)
このコンボボックスは単体で(別のテストプログラムを作って)動かしても順番がおかしいのでしょうか?

[補足]
どう考えても変数の寿命を考えるとやばい気がするんですが。
char character[5][10] = {"A","B","C","D","日本"}; ← これです。

Re: ダイアログプロシージャのコンボボックスの制御がうまくいかない。

Posted: 2012年3月28日(水) 22:57
by s707
softya(ソフト屋)様、ご返信ありがとうございます。

コンボボックス単体で試してみました。
思っていたのと違う所に原因があったようです。

ComboBox_SetCurSelとComboBox_GetCurSelを変えました。

コンボボックスのリストも表示されていなかったようなので
ボックスサイズを縦に拡大しました。

もうちょっとで解決できそうです。ありがとうございます。

Re: ダイアログプロシージャのコンボボックスの制御がうまくいかない。

Posted: 2012年3月30日(金) 12:57
by s707
解決しました。