Hallo Leute,
ich versuche gerade das Beispiel "listing_10.3" aus dem Buch "C++ für
Spieleprogrammierer" dahingehend zu ändern, dass für die Funktion
"ErstelleSteuerelemente" ein Rückgabewert definiert wird.
Prosa hierzu aus dem Buch:
"Im Anschluss daran wird die Funktion *ErstelleSteuerelemente"
aufgerufen. Wenn man es genau nimmt, dann müsste auch diese Funktion
einen Wert zurückliefern, anhand dessen man prüfen kann, ob alles
richtig funktioniert hat. Dazu müsste man dann die einzelnen Handles
überprüfen, die man in der Funktion ErstelleSteuerelemente
zurückgeliefert bekommt."
Hier ist der gezeigte Code aus dem Buch
Der Autor spricht von mehreren Handles, die man zurückgeliefert bekommt.
Ich frage mich nur, wie man die Funktion deklarieren muss, um mehrere
Handles zu erhalten?
Statt
Joachim schrieb:> Der Autor spricht von mehreren Handles, die man zurückgeliefert bekommt.> Ich frage mich nur, wie man die Funktion deklarieren muss, um mehrere> Handles zu erhalten?
Nö.
Davon spricht er nicht.
Er spricht davon, dass in der Funktion ErstelleSteuerelemente eine ganze
Latte von CreateWindow Aufrufen gemacht wird, von denen kein einziger
überprüft wird, ob sie auch gut gegangen sind. Sprich: Ob die Handles,
die sie geliefert haben auch gültig sind.
Und er spricht davon, dass die Funktion ErstelleSteuerelemente ihrem
Aufrufer mitteilen sollte: Hör mal, ich hab da versucht ein paar Fenster
mittels CreateWindow anzulegen, aber da ist was schief gelaufen.
Er spricht von 'einem Wert, den man zurückliefern müsste'. Aber an
keiner Stelle sagt er, dass dieser Wert der/die Handles selber sein
müssen. Nur weil sich das in ErstelleHauptfenster so angeboten hat,
heißt das ja noch lange nicht, dass das hier auch so sein muss. Ein BOOL
beispielsweise wäre absolut fein.
>Ein BOOL beispielsweise wäre absolut fein.
OK, dann kann man diese Überprüfungen innerhalb der Funktion vornehmen.
Sobald eine Überprüfung fehlschlägt, setze ich den Rückgabewert auf
FALSE.
Vielen Dank für die Klarstellung.
>Das Buch ist wohl schon etwas älter.
Es liest sich jedenfalls sehr gut.
VG, Joachim
CreateWindow liefert NULL, wenns Fenster erstellen schief ging.
Wenn man "void ErstelleSteuerelemente (HWND hWnd, HINSTANCE hInst)"
z.b. zu "int ErstelleSteuerelemente (HWND hWnd, HINSTANCE hInst)"
ändern würde,bei jedem CreateWindow auf NULL prüft und im true-fall ein
"return NULL" ausführt und am Ende nach den CreateWindow-aufrufen ein
"return 1" einfügen würde, könnte man in der Main mit if prüfen ob alles
gut gelaufen ist und mit GetLastError und Formatmessage sogar noch den
Anwender anschnauzen und das Programm beenden.
Es empfiehlt sich vielleicht das du dir mal die Win32-API besorgst, z.b.
die Hilfedatei Win32API-Big. Des Englischen mächtig sein ist aber
pflicht.
Und Mister DirectX ... Viel Spaß bei Dialogen und DirectX.
Hallo,
habe jetzt eine Bool-Variable in der Funktion "ErstelleSteuerelemte"
eingeführt, die die zurückgelieferten Handles überprüft. Funktioniert,
soweit sogut.
Nun habe ich im Zusammenhang dieses Beispiels noch eine Frage bezüglich
der verwendeten Handles. Im gezeigten Beispiel werden die Handles
"hText", "hEditBox", "hUebernehmen", "hBeenden" global deklariert.
Möchte man die globalen Deklarationen vermeiden, so müsste man die
Handles übergeben.
Ich würde also hergehen und die Handles in "WinMain" deklarieren und der
Funktion "ErstelleSteuerelemente" übergeben, also so:
Joachim schrieb:> Nun frage ich mich, wie die Callback-Funktion auf diese Handles> zugreifen kannn, wenn sie nicht global deklariert sind?
Und spätestens an dieser Stelle sind wir wieder an dem Punkt angelangt,
an dem man ohne ein dezidiertes C-Buch und das damit verbundene
Basiswissen nicht mehr weiterkommt.
Nichts gegen dein Buch. Nichts gegen Spieleprogrammierung.
Aber erst mal kommt: Beherrsche dein Handwerk
Im konkreten: Unterschied zwischen 'Call by Value' und 'Call by
Reference' und wie sich dieser Unterschied in C manifestiert.
1
voidfoo(inti)
2
{
3
printf("%d\n",i);
4
}
5
6
intmain()
7
{
8
foo(5);
9
}
1
voidfoo(int*i)
2
{
3
*i=8;
4
}
5
6
intmain()
7
{
8
intj;
9
10
foo(&j);
11
printf("%d\n",j);
12
}
Dein Spiele-Buch setzzt voraus, dass du mit C an sich nicht mehr auf
Kriegsfuss stehst. Es könnte für dich daher noch ein wenig über deinem
allgemeinen C-Niveau sein, was du in Kürze alles sehen wirst.
Hallo Karl Heinz,
dein Beispiel bezüglich "Call-By-Value" und "Call-By-Referenz" ist mir
geläufig. Hierzu gibt es in besagtem Buch auch ein Kapitel, das ich
durchgearbeitet habe.
Dennoch bin ich mir nicht im Klaren darüber, wie ich dies auf die
Handles übertragen kann?
VG, Joachim
Die Funktion "WindowProc" kann doch bezüglich ihrer Parameter nicht
erweitert werden?
Also wie kann ich hier die Handles als Paramter (sei es als
"Call-By-Value" oder als "Call-By-Reference") übergeben?
VG, Joachim
>>> Die Funktion "WindowProc" kann doch bezüglich ihrer Parameter nicht> erweitert werden?
Was willst du mit der WindowProc?
Du hast eine Funktion ErstelleSteuerelemente und die soll jetzt Werte
(nämlich die Handle Werte) nach aussen liefern. In völliger Analogie zu
meiner 2.ten Funktion foo, die eben einen int nach aussen liefert.
Die Funktion WindowProc interessiert hier doch keinen.
>> // Globale Variablen>> HWND hText; // Handle für den eigentlichen Text>> HWND hEditBox; // Handle für die Editbox>> HWND hUebernehmen; // Handle für Button "Übernehmen">> HWND hBeenden; // Handle für Button "Beenden">> Nun frage ich mich, wie die Callback-Funktion auf diese Handles>> zugreifen kannn, wenn sie nicht global deklariert sind?
hab ich was übersehen ?
Stefan
Autsch.
Mein Fehler.
In der Zwischenzeit hat sich das Topic verändert. Ging es ursprünglich
im die Init-Sequenz, in der die Fenster erzeugt werden, hast du den
Focus ja jetzt auf die Callback Funktion verschoben. Das hab ich nicht
mitbekommen.
Sorry, für die Konfusion.
Die Antowort: keine Chance. Die müssen global sein.
>Die Funktion WindowProc interessiert hier doch keinen.
Die Funktion WindowProc verwendet doch bspw. "hEditBox"
1
...
2
GetWindowText(hEditBox,szText,256);
Im Falle global deklarierter Handles kennt die Funktion WindowProc
den Handle "hEditBox". Aber woher nimmt sie diese Information, wenn die
Handles nicht global deklariert sind?
Sorry, aber ich stehe auf dem Schlauch.
VG, Joachim
Aus dem Buch:
"Wenn Du in den vorherigen Kapiteln aufgepasst hast, dann weißt Du, dass
man globale Variablen meiden sollte, wo es nur geht (und es geht fast
immer). Dass diese Regel hier gebrochen wurde ... dass der Quelltext
einfacher gehalten und leichter zu lesen sein sollte. Da es in diesem
Kapitel keine Aufgabe mehr geben wird, wäre es nicht verkehrt, wenn Du
im Anschluss versuchen würdest, das Programm so umzuschreiben, dass die
globalen Variablen vermieden werden können."
VG, Joachim
Joachim schrieb:> Aus dem Buch:>> "Wenn Du in den vorherigen Kapiteln aufgepasst hast, dann weißt Du, dass> man globale Variablen meiden sollte, wo es nur geht (und es geht fast> immer). Dass diese Regel hier gebrochen wurde ... dass der Quelltext> einfacher gehalten und leichter zu lesen sein sollte. Da es in diesem> Kapitel keine Aufgabe mehr geben wird, wäre es nicht verkehrt, wenn Du> im Anschluss versuchen würdest, das Programm so umzuschreiben, dass die> globalen Variablen vermieden werden können."
Du kannst natürlich die globalen Variablen in Funktionen verstecken.
Das ist aber nur syntaktischer Zucker. Das Grundproblem wird dadurch
nicht gelöst. Irgendetwas muss global verfügbar sein.
Allenfalls könnte man noch eine Datenstruktur an den Window Data Member
des Hauptfensters klemmen und dort die Werte unterbringen. Denn den hWnd
des Hauptfensters kriegst du in der WindowProc frei Haus geliefert.
Wobei ich mir jetzt aber ehrlich gesagt nicht sicher bin, ob die
WindowProc immer nur für das Hauptfenster aufgerufen wird. Ist schon zu
lange her, dass ich die Windows-API auf dieser Ebene programmiert habe.
http://msdn.microsoft.com/en-us/library/aa930761.aspx
WM_COMMAND wNotifyCode = HIWORD(wParam);
wID = LOWORD(wParam);
hwndCtl = (HWND) lParam;
wNotifyCode
Value of the high-order word of wParam. Specifies the notification code
if the message is from a control. If the message is from an accelerator,
this parameter is 1. If the message is from a menu, this parameter is 0.
wID
Value of the low-order word of wParam. Specifies the identifier of the
menu item, control, or accelerator.
hwndCtl
Handle to the control sending the message if the message is from a
control. Otherwise, this parameter is NULL.
Stefan
also "irgendwas" muss immer global sein
und wenn es eine liste ist die die Window-handle den einzelnen Objekten
zuordnet (nicht sicher ob das geht, ...)
oder pro object-instance "eigene" callback Funktionen hat
(delphi macht das so ähnlich, einfach mal nach MakeObjectInstance(.. in
Forms.pas suchen)
Das vom TO gezeigte Programm lässt sich rein C kompilieren.
Es is kein Borland nötig! Keines der Handles muss global sein da
WM_COMMAND das Handle bei Bedarf liefert.
Stefan
Stefan schrieb:> Das vom TO gezeigte Programm lässt sich rein C kompilieren.> Es is kein Borland nötig! Keines der Handles muss global sein da> WM_COMMAND das Handle bei Bedarf liefert.> Stefan
Stefan
Sieh dir den Code an.
Wenn du bei Betätigung eines Buttons aus dem Edit Control dir den Text
abholen willst, musst du den Handle zum Edit-Control irgendwo
herkriegen. WindowProc liefert dir den nicht!
Der Teil
1
caseID_BTN_UEBERNEHMEN:
2
{
3
charszText[256];
4
5
// Text aus der Editbox holen
6
GetWindowText(hEditBox,szText,256);
7
8
// Diesen Text in das Label schreiben und den Text der Editbox löschen
9
SetWindowText(hText,szText);
10
SetWindowText(hEditBox,"");
11
return(0);
12
}
ist ohne irgendetwas Globales nicht machbar (mal vom Data Member
abgesehen. Aber so toll ist das dann auch wieder nicht)
Allenfalls könnte man noch mittels GetChildWnd (oder wie das heißt)
ausgehend vom Hauptfenster und der Resource-Id den Handle bestimmen.
Dann fungiert eben die Resource Id als das 'globale Element'.
Irgendeinen Tod muss man immer sterben, wenn Callbacks im Spiel sind und
es keine Möglichkeit gibt, wie die Applikation einen beliebigen Paramter
durch das Callback Interface durchkriegt.
>> Allenfalls könnte man noch mittels GetChildWnd (oder wie das heißt)>> ausgehend vom Hauptfenster und der Resource-Id den Handle bestimmen.http://msdn.microsoft.com/en-us/library/windows/desktop/ms645481(v=vs.85).aspx
HWND WINAPI GetDlgItem(
__in_opt HWND hDlg,
__in int nIDDlgItem
);
>> Dann fungiert eben die Resource Id als das 'globale Element'.
Na ja die ID's während der Erstellung per rand() zu generieren und dann
gezielt ein Fenster zu manipulieren wird dann echt schwer.
>> Irgendeinen Tod muss man immer sterben, wenn Callbacks im Spiel sind und>> es keine Möglichkeit gibt, wie die Applikation einen beliebigen Paramter>> durch das Callback Interface durchkriegthttp://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx
LONG WINAPI SetWindowLong(
__in HWND hWnd,
__in int nIndex,
__in LONG dwNewLong
);
Das wird dann aber echt abgefahren ;)
Edit erstellen
Label erstellen
Button erstellen , SetWindowLong MAKELONG(LabelID,EditID)
oder
Edit erstellen
Label erstellen SetWindowLong EditHandle
Button erstellen , SetWindowLong LabelHandle
Stefan