Hallo,
ich bin grad dabei mich ein wenig mit der Win32 API auseinander zu
setzten.
Nun bin ich auf ein Problem gestoßen, dass ich trotz googlen nicht lösen
konnte.
Ich habe ein Parent Window, sobald in dessen Menü ein eintrag angeklickt
wird, wird ein neues Window erstellt, das ein Child Window ist. Wird die
WM_CREATE Msg in der Loopback Funktion des Childs abgearbeitet, werden
noch Control Elemente erstellt. 2x Button, 2x Static text und 2x Edit
Fields.
Leider kann ich nicht auf die Edit Fields schreiben, da er den Cursor
gar nicht da rein setzt. Über die ID und den Parent Handle kann ich aber
Text vom Code aus einfügen. Das ist aber für ein Eingabefeld ehr
suboptimal.
Ich konnte das Problem soweit eingrenzen, dass ich weiß, dass es mit dem
Erstellen des ersten ChildWindow zu tun hat. Als Style habe ich dort
WS_OVERLAPPED und WS_CAPTION. Wenn ich diese Styles entferne
funktioniert alles wie es soll, nur leider sieht das Fenster dann nicht
mehr wie ein abgegrenztes Fenster aus, sondern geht nahtlos in das
Parent Window über.
Im Netz habe ich das Problem auch schon gefunden, leider ist die Lösung,
den Style wegzulassen keine Option für mich.
vllt hat ja hier jemand eine Idee, die mir weiterhilft.
Alex
WS_CHILDWINDOW durch WS_POPUP ersetzen. Kombination von WS_POPUP mit
WS_CHILD oder WS_CHILDWINDOW ist unsinnig, da WS_POPUP den beiden
anderen widerspricht und diese unterdrückt. Das WS_POPUP-Fenster ist
Application-modal, erscheint also vor dem Hauptfenster und läßt sich
nicht dahinter verschieben. Gegenteil: System-modales Dialogfenster.
PS: Gemeint war natürlich, WS_POPUP für das Unterfenster zu verwenden.
Steuerelemente, wie Button, Editbox etc., haben ja den Stil WS_CHILD.
Danke für die Hilfe, jetzt funktioniert es wie gewollt.
Eine Frage hätte ich dann aber doch noch:
Bei allen Child Windows kann man über ein HMENU Handle eine ID vergeben,
geht das auch bei POP UP Windows? Sobald ich versuche dort eine D z.b.
(HMENU)1 einzufügen, bekomme ich den System Error Code 1401 (invalide
Menu Handle).
Alex
Dazu kann ich jetzt nichts sagen, da ich mich mit WinAPI lange nicht
mehr beschäftigt habe. Ein Menu gab es bei mir nur in Hauptfenstern.
Falls Du ein Code-Schnipsel zum o.g. Problem mit ID und Handle hast,
dann poste es mal und schreibe genau, wo es einzufügen ist. Aus
Eve_API_Checker.zip habe ich nur das Wesentliche für die Fenster als
solche extrahiert, angepasst und mit einer alten CodeBlocks-Version
compiliert.
Also, bei dem Button"BACK" in der dritten Zeile von unten kann man ein
(HMENU) int ID eingeben. sollte jetzt der Button eine Message an das
System senden, wird der Integerwert im wParam mitgeschickt, so zusagen
als Kennzeichner, von welchem Button die Nachricht kommt.
Hallo Alex!
Hat leider länger gedauert. Mein Programm hat jetzt ein Unterfenster mit
Back-Button und Menu. Funktioniert auch alles, egal, ob das Child Window
WS_POPUP oder WS_CHILD ist. Allerdings war irgendwo zu lesen, daß ein
Child Window kein Menü haben kann. Verstehe ich jetzt auch nicht.
Ich weiß nicht, warum dein o.g. Code-Schnipsel nicht funktionieren soll,
habe jedoch für mein Programm auch einiges angepaßt. Das Back-Button hat
bei Dir die gleiche ID, wie ein vorhergehendes Element und die Buttons
sind alle BS_DEFPUSHBUTTON, sind also alle gleichzeitg Default-Buttons.
Das sollte wohl nicht so sein.
Nächster Schritt ist der Datenaustausch zwischen Programm und Editbox
und das Umschalten zw. den Elementen mittels Tab-Taste. Soweit bin ich
noch nicht. Gibt es neue Infos oder irgendwelche Fragen? Was ist mit dem
Öffnen von Dateien, soll da ein vom OS vordefinierter Windows-Dialog
verwendet werden oder etwas komplett selbstgestricktes? LG
Rainer V. schrieb:
> Funktioniert auch alles, egal, ob das Child Window> WS_POPUP oder WS_CHILD ist.
Korrektur: Im Unterfenster mit Stil WS_POPUP läßt sich ein Menü in der
Unterfensterprozedur ChildWndProc unter WM_CREATE einrichten und unter
WM_COMMAND auswerten. Im Grunde alles analog zum Menü im Hauptfenster.
Dagegen kann in einer SDI-Anwendung ein Unterfenster mit Stil WS_CHILD
oder WS_CHILDWINDOW kein Menü haben. Der Quellcode dafür wird bei mir
(CodeBlocks) zwar compiliert, aber es wird keine Menüleiste angezeigt.
So, ich hab mal wieder Zeit gehabt ein bissel zu Coden.
Jetzt kann man schon mal durch einzelne Fenster mit den Next und Back
Buttons navigieren. Aber ich glaube es wird langsam Zeit das Ganze in
Klassen zu packen, es wird unübersichtlich.
Ich habe das mit dem BS_DEFPUSHBUTTON nun mal angepasst, aber das
scheint noch nicht ganz zu funktionieren, den eig müsste ja nach dem
Öffnen des ChildWindows mit Enter der Button betätigt werden, macht es
aber nicht.
So wie es mit dem Fenster jetzt ist, gefällt es mir schon ganz gut. Nur
hab ich jetzt ein kleines Farbproblem, die Edit-Felder haben
unterschiedliche Hintergrundfarben und ich weiß nicht warum, ich hab
keine Farbe dafür eingestellt, und alle werden gleich initialisiert.
Hab den Quelltext nochmal dazugepackt.
Langsam gehts voran.
Alex
Alex schrieb:
> Edit-Felder haben unterschiedliche Hintergrundfarben
Welche Farben? Falls anstatt Weiss eine andere, blasse Farbe erscheint,
z.B. leicht gelblich, dann kann es am Display, Lichteinfall o.a. liegen.
Sowas kenne ich von alten Monitoren bzw. zuwenig Helligkeit/Kontrast.
Texthintergrund in deinem Programm ist bei mir immer weiss. "Please
enter your API Key information" in einer EditBox? Ist das so gewollt?
Habe mal Class EDIT durch STATIC ersetzt. Der Hintergrund ist dann aber
grau. Einen Stil für weissen Hintergrund finde ich nirgends, nur sowas:
SS_xxxFRAME = farbiger Rahmen um die TextBox, grauer Texthintergrund.
SS_xxxRECT = farblich ausgefülltes Rechteck in der TextBox.
xxx ist durch WHITE, GRAY oder BLACK zu ersetzen, z.B. SS_BLACKFRAME.
Leider verschwindet bei diesen Stilen der vorgegebene Text. Es gibt aber
sicher eine Funktion, um den Text nachträglich hineinzuschreiben.
Bei den interaktiven Elementen habe ich WS_TABSTOP zum Stil hinzugefügt.
Man sollte dann mittels Tab-Taste oder Shift-Tab von einem Element zum
nächsten gehen können, soweit ich mich erinnere. Funktioniert so nicht!
Ja das mit den Farben lag daran, dass ich einmal EDIT und einmal STATIC
als Window Class hate, ist jetzt behoben. Wenn ich heute Abend noch Lust
und Muse habe, werde ich mich mal daran machen, die API Key eingabe zu
verarbeiten und die Daten vom Server zu holen. Das mit dem Next Button,
das der nicht Fokus ist, werde ich dann auch angehen.
Alex
Der Next-Button hat bei mir immer Fokus. Sollte auch so ein, sonst wäre
BS_DEFPUSHBUTTON ja sinnlos. Ein SetFocus(hwndButton_NEXT) am Ende von
WM_CREATE in WindowChildProc() wäre eine Alternative. So könnte man den
Fokus auch auf das Editfeld setzen, um direkt mit Eingaben zu beginnen.
Um den Datentransfer von/zu Control Elementen in anderen Fenstern muß
ich mich auch mal kümmern. Ich kenne sowas aus TPascal für Windows 3.x,
das ist lange her. Hier noch was zum Thema "Private Botschaft senden
zwecks Kommunikation zw. Fenstern, SendMessage() und Identifier WM_APP":
http://www.win-api.de/tutorials.php -> 11.Child Window
Habe es eben ausprobiert. Senden vom Hauptfenster nach Child Window geht
noch nicht, weil mir das Child-Handle fehlt. In umgekehrter Richtung
habe ich ja GetParent(Childhwnd) als Ziel-Handle. Das reicht schon mal,
um das Hauptfenster über Aktionen im Unterfenster zu informieren. LG
Ich hab mein Problem mit dem NEXT Button gefunden. Die Keyboard Messages
für Tab und Enter werden scheinbar nicht richtig weitergeschickt. Wenn
ich im Hauptfenster zwei Buttons erstelle, dann kann ich mit Tab
zwischen den beiden wechseln, im ChildWindow kommt das aber nicht
richtig an, sodass auch keine Umschaltung stattfinden kann.
Eig sollte mit SetFocus() ja das angegebene Fenster den Keyboard Fokus
erhalten, aber das geht iwie noch nicht ganz.
Alex schrieb:
> Wenn ich im Hauptfenster zwei Buttons erstelle, dann kann ich mit Tab> zwischen den beiden wechseln
Funktioniert bei mir trotz WS_TABSTOP nicht, auch Drücken von <Enter>
ist wirkungslos. Die Buttons muß ich mit der Maus anklicken, sonst
passiert nichts. Bei Dialog-basierten Fenstern ist das anders. Da gibt
es intern einen Mechanismus zum Weiterschalten mit Tab- und Pfeiltasten.
Und wenn der Fokus nicht auf einem Editfeld sitzt, dann entspricht
Drücken von Enter dem OK-Button und die Esc-Taste dem Cancel-Button.
Habe es mit CodeBlocks-Beispiel für Dialogfenster ausprobiert. Da haben
die Buttons nur den Stil WS_VISIBLE|WS_TABSTOP, sonst nichts. Ich nehme
an, daß man den Tasten-Mechanismus bei frame-based Fenstern erst selber
programmieren muß. Bin mal gespannt, wie es bei AutoRadioButtons wird.
@Alex
Welchen Compiler/IDE verwendest Du?
while(GetMessage(&msg,NULL,0,0))// Run the message loop.
2
{
3
if(!IsDialogMessage(hwnd,&msg))
4
{
5
TranslateMessage(&msg);
6
DispatchMessage(&msg);
7
}
8
}
Damit die Message richtig verarbeitet werden kann, muss der
IsDialogMessage() Funktion das Handle und die Message übergeben werden,
je nach dem, ob es dann ein Enter oder Tab ist, wird das verarbeitet.
Ich benutze MSVC++.
Nur, dass im Child Window die Tabs umschalten geht bei mir noch nicht.
Alex
IsDialogMessage() übernimmt die gesamte Übersetzung und Verteilung von
Botschaften für das Dialogfenster. Im Gegensatz zu anderen Fenstern sind
einige Tasten/-kombinationen den typ. Dialogfensterfunktionen zugeordnet
und können nicht anderweitig verwendet werden. Z.B. dienen Pfeil- u.
Tab-Tasten zum Umschalten zw. den mit WS_TABSTOP markierten Elementen.
Wird IsDialogMessage() eingesetzt, dann dürfen Botschaften NICHT auch
noch an TranslateMessage() und DispatchMessage() übergeben werden!
So steht es jedenfalls in meiner TPascal Hilfe wie auch bei MSDN:
WinAPI->Dialog Boxes->Dialog Box Functions->IsDialogMessage
http://msdn.microsoft.com/en-US/library/windows/desktop/ms645498(v=vs.85).aspx
Dialog-Tasten in der modalen Dialogbox, Dialog Keyboard Interface:
http://msdn.microsoft.com/en-US/library/windows/desktop/ms644995(v=vs.85).aspx#keyboard_iface
Hier gibt es auch einiges, WinAPI Index:
http://msdn.microsoft.com/en-US/library/windows/desktop/ff818516(v=vs.85).aspx
PS: Es gibt Unterschiede zw. der modalen u. der nicht-modalen Dialogbox.
Und dann gibt es noch die Möglichkeit, ein Dialogfenster komplett inkl.
Control-Elementen aus einer Ressourcendatei zu laden. Dann kann man Code
in main.cpp einsparen, muß allerdings ein Ressourcenscript schreiben und
mit windres.exe oder rc.exe zu einer Ressourcendatei *.res compilieren.
Also langsam bin ich am Verzweifeln. Im Hauptfenster geht das
Durchtabben ohne Probleme. Aber in dem Pop Up Window bekomme ich immer
nur diesen ding sound zuhören. Ich hab jetzt schon 2 Tage gesucht im
Netz und finde einfach keine Lösung.
Ist es vllt besser für solche Sachen Dialogfenster zu nehmen?
Alex
Sry für den Doppelpost.
Manschmal kann die Lösung so einfach sein.
1
while(GetMessage(&msg,NULL,0,0))// Run the message loop.
2
{
3
if(msg.hwnd==hwnd)
4
{
5
if(!IsDialogMessage(hwnd,&msg))
6
{
7
TranslateMessage(&msg);
8
DispatchMessage(&msg);
9
}
10
}else
11
{
12
if(!IsDialogMessage(Childhwnd,&msg))
13
{
14
TranslateMessage(&msg);
15
DispatchMessage(&msg);
16
}
17
}
18
}
Damit die Nachrichten am richtigen fenster ankommen, einfach eine
If-Abfrage je nach handle vom dem sie kommen. Jetzt funktioniert das
Durchtabben im PopUp Window und im Hauptwindow.
Gab grad wieder ein kleines Erfolgserlebnis.
Alex
Funktioniert bei mir leider nicht. Habe den Code mal eingefügt, es wird
gar kein Fenster angezeigt. Selbst dann nicht, wenn die Teile für Handle
Childhwnd mittels goto-Befehl übersprungen werden. Leider gibt es bei
MSDN kaum komplette Code-Beispiele für frame- und dialog-basierte
Fenster, von solchen mit Kind-Fenstern ganz zu schweigen. Ich suche noch
mal woanders.
Alex schrieb:
> Ich benutze MSVC++.
Kenne ich nun nicht, hatte nur unter Win98 mal eine Demoversion VC++6.
Da war RC.exe v.3.0 enthalten, damit habe ich Ressourcendateien für
TPascal-Programme compiliert. Dieselben Ressourcenscripte benutzte ich
heute für CodeBlocks-Projekte mit Fenstern, Res-Compiler ist
MinGW\windres.exe.
Ist dieses MSVC++ in Deutsch?
Guck mal ob das bei dir Funktioniert.
Mann kann Visual Studio 2013 kostenlos bei MS herunterladen. Damit man
es aber länger als 30 tage benutzten kann, muss man sich aber kostenlos
registrieren.
Funktioniert in weiten Teilen offenbar so, wie gewollt, außer:
Beim Zurückgehen von der Testseite auf vorhergehende Seiten wird im
Next-Button anstatt "Next" der Text "Speichern" angezeigt.
Das Next-Button funktioniert erst dann mit der Enter-Taste, nachdem der
Fokus mittels Tab-Taste hin und her bewegt und mind. zum 2. Mal auf das
Next-Button gesetzt wurde. Das war mit anderen Buttons zuweilen ebenso.
Ich habe dann in WindowChildProc()\WM-CREATE in CreateWindow() für das
Next-Button den Stil von BS_DEFPUSHBUTTON in BS_PUSHBUTTON geändert.
Damit ging es besser. Vermutl. darf kein Default-Button definiert und
dann der Fokus mit einer Anweisung woandershin (hier Editfeld) gesetzt
werden. Das würde auch dem Sinn des Dialog-Tasten-Mechanismus
widersprechen.
Das Programm, wo ich o.g. Code-Schnipsel für GetMessage() eingefügt
habe, funktioniert jetzt. Ich hatte zusätzl. die Fensterhandles mit
if-Befehl auf Null geprüft und bin damit aus der Nachrichtenschleife
gesprungen. Kein Wunder, daß da kein Fenster angezeigt wurde.
Ich hab wieder mal ein bissel was gemacht, gibt jetzt einen schönen
Hintergrund, und hab mich in die Resource files Thematik eingearbeitet.
Als nächstes kommt dann aber die Serverabfrage und das speichern der
erhaltenen Daten.
Alex
Bin schon länger mit Übersetzung des WinAPI-Index auf MSDN beschäftigt.
Kann Jahre dauern, etwa 0.1% sind fertig und kein Ende in Sicht.
Ich habe für Compiler RC.exe 3.0 eine Anleitung inkl. Beschreibung der
Anweisungen im Ressourcenscript. Alles gesammelte Infos aus der Hilfe zu
VC6 o.a. aus der Zeit von Win98, eigene, manchmal holperige Übersetzung
ins Deutsche, evtl. nicht vollständig, reicht aber für den Anfang. Die
Befehls-Syntax ist auch für Compiler windres.exe weitgehend gültig.
Falls Bedarf besteht, kann ich es überarbeiten u. hier posten, ~200KB.
Ein paar Code-Beispiel/Ressourcenscripte hätte ich sicher auch noch.
In o.g. Codes ist mir aufgefallen, daß die Control-IDs oft kleiner als
100 sind. Hier einige Tips zu Ressourcen-IDs, soweit ich das kenne:
ID 1 ist für Ressource VERSIONINFO reserviert, dies muß ID 1 sein! IDs
1-99 sind für Windows reserviert, IDs 32768-65535 für MFC/VisualStudio.
Für Ressourcen des Benutzers bleiben die IDs 100-32767.
Bei Static Controls, deren Text nicht geändert wird und die nicht mit
Tab- oder Pfeil-Tasten angesprungen werden, muß nicht jedes Static
Control eine eigene, eindeutige ID haben. Für solche darf die ID -1 bzw.
65535 benutzt werden: #define idc_STATIC -1
Bis die Tage. LG
Hallo,
ich hab die letzten 2 Wochen immer mal wieder dran gearbeitet, einige
Sachen komplett umgeschrieben und mich den Resourcen zugewandt. Alle
Fenster, welche ich vorher in der jeweiligen Callback Funktion erstellt
habe, sind jetzt als Resourcen in einer .rc-Datei untergebracht. So wird
es wesentlich einfacher, neue Fenster zu erstellen und zu verändern. Der
code in der main.cpp ist dadurch auch wesentlich schlanker geworden.
Weiterhin habe ich mich mit den Hintergründen beschäftigt. Jetzt sieht
es erstmal nicht so leer aus. Ob es am Ende so bleiben wird ist aber
noch nicht sicher, da es doch ganz schön ablenkt.
Wie schon mehrmals angekündigt, aber noch nicht umgesetzt, kommt
demnächst die eigentliche Abfrage der Serverdaten über die API. Erstmal
der Import, der Account Daten beim Eingeben eines neuen API-Keys.
Alex
Sieht doch ganz gut aus. Habe gedacht, ich wäre Astronaut. Ich sehe es
mir später noch genauer an, im Moment leider kaum Zeit. Dringende Frage:
welches ZIP-Programm ist empfehlenswert? WinZip mit/ohne Self-Extractor
ist ja nicht billig. Gibt es zuverlässige, seriöse Freeware, vllt. auf
Sourceforge? Bis dahin. LG
So ich habe man wieder ein bissel rumgespielt.
Die Abfrage eines API-Keys funktioniert jetzt. Zur Zeit ist der zu
Testzwecken noch hardgecodet, damit man nicht immer so viel tippen muss.
Es wird jetzt, wenn auf dem Account Chars verfügbar sind eine Checkbox
angezeigt, die den Namen enthält und dann später die entsprechenden
Daten zur Weiterverarbeitung markiert.
Leider ist der Code noch sehr unaufgeräumt. Ich benutze TinyXML2 um die
Daten, welche vom Server kommen zu Parsen. Scheinbar muss man sich da
noch eine eigene Klasse bauen, damit man da schnell mit arbeiten kann.
Hier mal der Link zum aktuellen Stand:
https://www.dropbox.com/sh/7dm2it1wum2ek03/AAApmsMD2IoFs6kLmTGMTY8Na?dl=0
Ich benutze übrigens die Testversion von Winrar um die Sachen zu packen.
Alex
Hm, ich habe jetzt ein Problem festgestellt.
Wenn ich einen Release der Anwendung Kompilierewar auf einem anderen PC
starten, leider kannn ich das Fenster für "Add API Key nicht mehr
öffnen. Sobald ich darauf klicke, kommt kurz die Eieruhr, es passiert
aber nichts.
Debugge ich das Relase, so geht er in den richtigen Switch-Case, sobald
die Funktion
aufgerufen wird, geht das Programm in die Callbackfunktion der Box.
Soweit so gut, aber nun bekomme ich Probleme. Die Messages die hier
ankommen sind 2x WM_SETFONT, das ist auch noch richtig, dann bekomme ich
ein WM_DESTROY und das Fenster verschwindet wieder im Nirvana.
GetLastError() liefert aber leider keinen Fehler. Kann es sein, dass
beim SetFont der einzelnen Elemente ein Fehler auftritt, das System aber
nicht meckert?
Gibt es eine möglichkeit zu gucken, was bei den Childelementen passiert,
wenn diese ein WM_SETFONT erhalten?
Alex
Habe es von Dropbox geladen, mit Winrar-Testversion ausgepackt. Erstmal
muß ich die Sache mit Handle HINTERNET klären, weil für GetData.cpp bei
mir der Fehler kommt, daß dieser Handletyp nicht definiert ist. Habe auf
MSDN\WinInet-API einiges durchgelesen und in GetData.cpp eingefügt:
#include "WinInet.h"
Jetzt kommt der Fehler, daß hinter Zeile HINTERNET EVE_API_HANDLE; ein
Konstruktor o.a. erwartet wird. Nun weiß ich nicht, wie und an welcher
Stelle GetData.cpp im Code eingebunden wird. Der Textblock ab Aufruf von
InternetOpen() scheint in der Luft zu hängen. Habe alle Quelltexte im
CodeBlocks-Projekt-Explorer aufgelistet, sollte funktionieren. Kann es
sein, daß bei Download/Entpacken Text verloren gegangen ist?
Alex schrieb:
> kannn ich das Fenster für "Add API Key nicht mehr öffnen. Sobald ich> darauf klicke, kommt kurz die Eieruhr, es passiert aber nichts.> Debugge ich das Release,...
Vllt. vertrödelst Du zuviel Zeit mit dem Debugger. Ich habe alles das,
was nicht Anwendungsgrundgerüst ist bzw. nicht zur Anzeige der Fenster
nötig ist, aus dem Code entfernt und in DialogProc()\WM_CREATE\switch
eine MessageBox eingefügt. Da die MsgBox wider Erwarten nicht angezeigt
wurde, ist vor WM_CREATE ein Fehler aufgetreten. Um es kurz zu machen:
Siehe in Resource.rc: IDD_ADD_API_KEY DIALOGEX...
CONTROL "...", IDL_LINK, "SysLink", WS_TABSTOP,...
Was ist Control-Klasse "SysLink"? Habe das mal zum Test durch "STATIC"
ersetzt. Prompt erscheint der Dialog mit dem Link in einer TextBox. Weit
und breit keine Sanduhren zu sehen. LG