TextOut einer Long-Variablen bei einer W32-Fensterausgabe

Bobblz

Mitglied
Hallo zusammen,

ich habe ein Problem bei der Erstellung einer W32-Anwendung.
Ziel ist es, das jedes Fenster die Anzahl der Mousemoves zählt und ausgibt. Ich zähle mit hilfe der Nachricht WM_MOUSEMOVE und nutze den cbWndExtra-Speicher zum speichern des Wertes.

Aber wenn ich den Wert ausgebe kommt es anscheinend zu einem Speicherüberlauf. Er schreibt die 1 ordnungsgemäß, bei den folgenden kommen sinnlose Zeichen hinten dran bis dann schlussendlich eine Exception kommt.

Weis leider nicht woran das liegt :(

C++:
// Aufgabe_1.cpp : Definiert den Einstiegspunkt für die Anwendung.
//

#include "stdafx.h"
#include "Aufgabe_1.h"
#include "stdio.h"
#include "atlconv.h"


#define MAX_LOADSTRING 100

// Globale Variablen:
HINSTANCE hInst;								// Aktuelle Instanz
TCHAR szTitle[MAX_LOADSTRING];					// Titelleistentext
TCHAR szWindowClass[MAX_LOADSTRING];			// Klassenname des Hauptfensters

// Vorwärtsdeklarationen der in diesem Codemodul enthaltenen Funktionen:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Hier Code einfügen.
	MSG msg;
	HACCEL hAccelTable;

	// Globale Zeichenfolgen initialisieren
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_AUFGABE_1, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Anwendungsinitialisierung ausführen:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_AUFGABE_1));

	// Hauptnachrichtenschleife:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}



//
//  FUNKTION: MyRegisterClass()
//
//  ZWECK: Registriert die Fensterklasse.
//
//  KOMMENTARE:
//
//    Sie müssen die Funktion verwenden,  wenn Sie möchten, dass der Code
//    mit Win32-Systemen kompatibel ist, bevor die RegisterClassEx-Funktion
//    zu Windows 95 hinzugefügt wurde. Der Aufruf der Funktion ist wichtig,
//    damit die kleinen Symbole, die mit der Anwendung verknüpft sind,
//    richtig formatiert werden.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= sizeof(LONG);  // Extraspeicher pro Fenster holen
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_AUFGABE_1));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_AUFGABE_1);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNKTION: InitInstance(HINSTANCE, int)
//
//   ZWECK: Speichert das Instanzenhandle und erstellt das Hauptfenster.
//
//   KOMMENTARE:
//
//        In dieser Funktion wird das Instanzenhandle in einer globalen Variablen gespeichert, und das
//        Hauptprogrammfenster wird erstellt und angezeigt.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   SetWindowLong(hWnd,0,0);
   
   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNKTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  ZWECK:  Verarbeitet Meldungen vom Hauptfenster.
//
//  WM_COMMAND	- Verarbeiten des Anwendungsmenüs
//  WM_PAINT	- Zeichnen des Hauptfensters
//  WM_DESTROY	- Beenden-Meldung anzeigen und zurückgeben
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	HWND neuesFenster;
	LPCWSTR lpcwstr_string = L"";
	char s[20] = "";
	long a = GetWindowLong(hWnd,0);

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Menüauswahl bearbeiten:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd); 
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		_snprintf_s(s, _countof(s), "%d", a);
		lpcwstr_string = A2BSTR(s);
		TextOut( hdc, 10, 10, lpcwstr_string, a );
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		// Wenn es kein Elternfenster gibt, dann Prozess killen
		if (!GetParent(hWnd)) {
			PostQuitMessage(0); // Prozess killen
		}
		break;
	case WM_RBUTTONDOWN:
		neuesFenster = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CHILD | WS_CLIPSIBLINGS,CW_USEDEFAULT, 0, 
			CW_USEDEFAULT, 0, hWnd, NULL, hInst, NULL);
		SetWindowLong(neuesFenster,0,0);
		ShowWindow(neuesFenster, SW_SHOW);
		UpdateWindow(neuesFenster);
		// sntprintf() für Ausgabe
		break;
	case WM_MOUSEMOVE:
		a = a+1;
		SetWindowLong(hWnd,0,a);
		InvalidateRect(hWnd, NULL, true);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Meldungshandler für Infofeld.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

Wäre für jede Hilfe dankbar.
 
Zuletzt bearbeitet von einem Moderator:
Hi.

Außerdem mußt du in jeder Funktion in der du die ATL Konvertierungsmakros verwendest am Anfang der Funktion USES_CONVERSION; spezifieren.

Und warum wandelst du in einen BSTR um? (und nicht einfach in einen Wide-Character-String?) Mal abgesehen davon, dass A2BSTR veraltet ist.

Warum wandelst du überhaupt um - nimm doch einfach überall statt char TCHAR und benutze die generischen Textfunktionen aus tchar.h (statt _snprintf_s einfach _sntprintf_s etc.).

Gruß
 
Zurück