C++ Winapi Variable in Funktionsaufruf

Wenn du eine Variable in einer Funktion hast, kannst du der ja irgendwelche Werte zuweisen.
Wenn die Funktion aber fertig ist und ein zweites Mal aufgerufen wird, steht in der Variable nicht mehr der Wert, den sie am Ende der ersten Funktion gehabt hat. Der wird jedesmal am Funktionsende weggeputzt.

Wenn du die Variable aber als static anlegst, behält sie nach einem Funktionsdurchgang ihren zuletzt aktuellen Wert und hat den beim nächsten Aufruf noch immer.
Dann kann sie wieder normal gelesen und verändert werden, und behält sich am Ende vom zweiten Durchgang ihren aktuellen Wert für den dritten Aufruf ...usw.
Sie wird also am Funktionsende nicht gelöscht.

Anlegen kannst du sowas, indem du einfach static vorne hinschreibst, zB:
C++:
static int i;

Nur noch als Hinweis: Außer bei funktionsinternen Variablen gibts static auch noch bei Strukturen/Klassen. Hat dort aber einen leicht anderen Sinn.

Gruß
 
Ich glaub, langsam kapiere ich´s. :D
Aber ich verstehe nicht ganz, wie ich das jetzt im einem Programm lösen kann.

Wäre echt super von euch, wenn ihr mir da noch helfen könntet.

Lg

PS: Sorry, dass ich so spät antworte.
 
Du solltest die Variabeln, die du in verschiedenen Nachrichten verwendest als statische Variabeln der Funktion deklarieren damit du überall darauf zugreifen kannst.
 
Hi,

erstmal ´tschuldigung, dass ich wieder so spät antworte. Ich war und bin ziemlich krank.
Jetzt wieder zurück zu Thema: :)


Wenn ich die meine Variablen vor "switch(message)" deklariere, erkennt WM_PAINT es zwar, es ist aber einfach nur 0.

Viele Grüße und nochmal danke!
 
Ach ja! Noch was.
Ich hab vorher versucht mit einer if-Schleife zu programmieren, dass er nur zeichnet, wenn iPosX etc. nicht null sind. Er akzeptiert aber nur Variablen vom Typ const char.
Das versteh ich nicht!
 
Zeig deinen akuellen Code. Sonst können wir nur raten.

Und eine Schliefe wiederholt sich. If ist keine Schleife, sondern einfach eine Bedingung.
 
Hier der Code (ich hab mich davor falsch ausgedrückt, es funktioniert einfach nicht :( ):

Code:
// Linie zeichnen.cpp : Definiert den Einstiegspunkt für die Anwendung.
//

#include "stdafx.h"
#include "Linie zeichnen.h"

bool Zeichnen = false;

#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_LINIEZEICHNEN, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

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

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

	// 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		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LINIEZEICHNEN));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_LINIEZEICHNEN);
	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_SYSMENU,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   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;

	static int iPosX;
	static int iPosY;
	static int jPosX;
	static int jPosY;

	switch (message)
	{
    case WM_LBUTTONDOWN:
		if (Zeichnen)
	{
    iPosX = LOWORD(lParam);
    iPosY = HIWORD(lParam);
    wchar_t waCoord[20];
	}
    break;
   case WM_RBUTTONDOWN:
		if (Zeichnen)
    {
    jPosX = LOWORD(lParam);
    jPosY = HIWORD(lParam);
    wchar_t waCoord[20];
	}
    break;
	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);
		// TODO: Hier den Zeichnungscode hinzufügen.
		HPEN hPenOld;

		{

		int Linie = MessageBox(hWnd, _T("Möchtest du eine Linie ziehen?"), _T("Zeichnen?"), MB_YESNO);

		switch (Linie)
		{
		case IDYES: 
			MessageBox(hWnd, _T("Du kannst jetzt eine Linie ziehen, indem du mit der linken Maustaste auf den Startpunkt und mit der rechten Maustaste auf den Endpunkt klickst!"), _T("Linie zeichnen"), MB_OK);
			if (iPosX != 0 && iPosY != 0 && jPosX != 0 && jPosY != 0)
			{
			HPEN hLinePen;
			COLORREF qLineColor;
			qLineColor = RGB(255, 0, 0);
			hLinePen = CreatePen(PS_SOLID, 7, qLineColor);
			hPenOld = (HPEN)SelectObject(hdc, hLinePen);

			MoveToEx(hdc, /* hier soll die Variable iPosX rein */  iPosX , /* hier soll die Variable iPosY rein */  iPosY, NULL);
			LineTo(hdc, /* hier soll die Variable jPosX rein */ jPosX, /* hier soll die Variable jPosY rein */ jPosY);

			SelectObject(hdc, hPenOld);
			DeleteObject(hLinePen);

			}

			break;
		case IDNO:  
			MessageBox(hWnd, _T("Und wofür hast du dann das Programm geöffnet?"), _T("****?"), MB_OK);
			break;

		}

		}

	


		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		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;
}

Und `tschuldigung nochmal.
 
Also da gibt es ein paar Dinge:
1. MessageBox innerhalb von WM_PAINT find ich jetzt nicht so eine tolle Idee. Mach das doch gleich bei Programmstart und brich das Programm bei nein ab.
2. WM_PAINT wird nur aufgerufen, wenn das Fenster neu gezeichnet werden muss. Das ist nur dann der Fall, wenn ein Teil des Fensters als veraltet markiert wurde.
3. Du solltest nachdem iPosX oder eine der anderen Variabeln in WM_LBUTTONDOWN bzw WM_RBUTTONDOWN zugewiesen wurden via InvalidateRect andeuten, dass das Fenster bitte neu gezeichnet werden soll.
 
Erstmal vielen Dank.
Ich glaub ich weiß jetzt wie´s funktioniert.

Ich hab nur noch ne Frage zu 1. :
Was bedeutet Programmstart?
Vor "switch(message)"?
 
Zurück