C++ WM_CHAR Message kommt nicht an!?

Magogan

Lieutenant
Registriert
Aug. 2013
Beiträge
606
Hi,

ich habe schon gegoogelt und in diversenen Foren nachgelesen, aber ich finde einfach den Fehler nicht. Aus irgendeinem Grund kommen keine WM_CHAR Messages an bzw. InterfaceClass::HandleCharInput wird nie ausgeführt. Die Maus-Messages kommen aber an und werden auch verarbeitet...

Mein Code:

Code:
#include "systemclass.h"


SystemClass::SystemClass()
{
	m_Application = 0;
}


SystemClass::SystemClass(const SystemClass& other)
{
}


SystemClass::~SystemClass()
{
}


bool SystemClass::Initialize()
{
	int screenWidth, screenHeight;
	bool result;


	// Initialize the width and height of the screen to zero before sending the variables into the function.
	screenWidth = 0;
	screenHeight = 0;

	// Initialize the windows api.
	InitializeWindows(screenWidth, screenHeight);

	// Create the application wrapper object.
	m_Application = new ApplicationClass;
	if(!m_Application)
	{
		return false;
	}

	// Initialize the application wrapper object.
	result = ApplicationClass::Initialize(m_hinstance, m_hwnd, screenWidth, screenHeight);
	if(!result)
	{
		return false;
	}

	ApplicationClass::WorldInitializationThreadHandle = CreateThread(0, 0, ApplicationClass::ThreadWorldInitialization, 0, 0, 0);

	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

	return true;
}


void SystemClass::Shutdown()
{
	// Release the application wrapper object.
	if(m_Application)
	{
		ApplicationClass::Shutdown();
		delete m_Application;
		m_Application = 0;
	}

	// Shutdown the window.
	ShutdownWindows();
	
	return;
}


void SystemClass::Run()
{
	MSG msg;
	bool done, result;


	ZeroMemory(&msg, sizeof(MSG));
	
	done = false;
	while(!done)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			
			switch(msg.message){
				case WM_QUIT:

					done = true;
					break;
			
				case WM_MOUSEWHEEL:
				case WM_RBUTTONDOWN:

					ApplicationClass::HandleMouseInput(msg.message, msg.wParam, msg.lParam);
					break;

				case WM_CHAR:

					InterfaceClass::HandleCharInput(msg.wParam, msg.lParam);
					break;

				default: break;
			}
		}
		else{
			
			if (NetworkClass::Error != 0){
				exit(NetworkClass::Error); // TBD
			}

			if(!Frame()){
				done = true;
			}
		}

	}

	return;
}


bool SystemClass::Frame()
{
	bool result;

	if (GetForegroundWindow() == m_hwnd){
		// Do the frame processing for the application object.
		result = ApplicationClass::Frame();
		if (!result)
		{
			return false;
		}
	}
	else{
		Sleep(100);
	}
	return true;
}


LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	return DefWindowProc(hwnd, umsg, wparam, lparam);
}


void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int posX, posY;


	// Get an external pointer to this object.	
	ApplicationHandle = this;

	// Get the instance of this application.
	m_hinstance = GetModuleHandle(NULL);

	// Give the application a name.
	m_applicationName = L"Application";

	// Setup the windows class with default settings.
	wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = m_hinstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm       = wc.hIcon;
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = m_applicationName;
	wc.cbSize        = sizeof(WNDCLASSEX);
	
	// Register the window class.
	RegisterClassEx(&wc);

	// Determine the resolution of the clients desktop screen.
	screenWidth  = GetSystemMetrics(SM_CXSCREEN);
	screenHeight = GetSystemMetrics(SM_CYSCREEN);

	// Setup the screen settings depending on whether it is running in full screen or in windowed mode.
	if(FULL_SCREEN)
	{
		// If full screen set the screen to maximum size of the users desktop and 32bit.
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
		dmScreenSettings.dmSize       = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth  = (unsigned long)screenWidth;
		dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
		dmScreenSettings.dmBitsPerPel = 32;			
		dmScreenSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		// Change the display settings to full screen.
		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);

		// Set the position of the window to the top left corner.
		posX = posY = 0;
	}
	else
	{
		// If windowed then set it to 800x600 resolution.
		screenWidth  = WINDOWED_SCREEN_WIDTH;
		screenHeight = WINDOWED_SCREEN_HEIGHT;

		// Place the window in the middle of the screen.
		posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth)  / 2;
		posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
	}

	// Create the window with the screen settings and get the handle to it.
	m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
						    WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
						    posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);

	// Bring the window up on the screen and set it as main focus.
	ShowWindow(m_hwnd, SW_SHOW);
	SetActiveWindow(m_hwnd);
	SetForegroundWindow(m_hwnd);
	SetFocus(m_hwnd);

	// Hide the mouse cursor.
	ShowCursor(false);

	return;
}


void SystemClass::ShutdownWindows()
{
	// Show the mouse cursor.
	ShowCursor(true);

	// Fix the display settings if leaving full screen mode.
	if(FULL_SCREEN)
	{
		ChangeDisplaySettings(NULL, 0);
	}

	// Remove the window.
	DestroyWindow(m_hwnd);
	m_hwnd = NULL;

	// Remove the application instance.
	UnregisterClass(m_applicationName, m_hinstance);
	m_hinstance = NULL;

	// Release the pointer to this class.
	ApplicationHandle = NULL;

	return;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
	switch(umessage)
	{
		// Check if the window is being destroyed.
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}

		// Check if the window is being closed.
		case WM_CLOSE:
		{
			PostQuitMessage(0);		
			return 0;
		}

		case WM_CHAR:
			
			InterfaceClass::HandleCharInput(wparam, lparam);
			return 0;
		
		case WM_KEYDOWN:
			return 0;

		// All other messages pass to the message handler in the system class.
		default:
		{
			return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
		}
	}
}

Hat jemand eine Idee, woran es liegen könnte? Das Fenster müsste doch den Keyboard-Fokus haben, ich verstehe das nicht...

Grüße,
Magogan
 
Zuletzt bearbeitet:
Auf die Schnelle: Kommentier mal case WM_KEYDOWN: return 0; aus. Das hebelt ja die Default Behandlung aus.

Ansonsten schau mal mit Spy++ was das Fenster so an Nachrichten kriegt.
 
Blublah schrieb:
Auf die Schnelle: Kommentier mal case WM_KEYDOWN: return 0; aus. Das hebelt ja die Default Behandlung aus.

Denke ich auch. Laut MSDN:

WM_CHAR message

Posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function.

Da du aber die WM_KEYDOWN-Message schon selber behandelst und das System die nie zu sehen bekommt, kann es doch zum dem oben rot markierten Ereignis gar nicht kommen.
 
Blublah schrieb:
Auf die Schnelle: Kommentier mal case WM_KEYDOWN: return 0; aus. Das hebelt ja die Default Behandlung aus.

Ansonsten schau mal mit Spy++ was das Fenster so an Nachrichten kriegt.
Hab kein Spy++, das gibt es nicht in der Express-Version...

Das Auskommentieren hat nichts gebracht, ich bekomme ja nicht einmal eine WM_KEYDOWN Message...

Edit: Okay, Lösung gefunden: Es lag daran, dass ich DirectInput genutzt habe und mir da die Tastatur exklusiv gesichert habe... Das sollte man natürlich nicht machen, wenn man noch WM_CHAR benutzen will...
 
Zuletzt bearbeitet:
Zurück
Oben