MDI und Callback Funktion
-
HALLO.
ich muss ehrlich sagen, dass ich nicht 100% weis, mit der GetModuleHandle funktion umzugehen.
ich denke einbinden muss ich GetModuleHandle in die CreateWindowEx, kann ich aber auch dort die erhaltenen daten in ein array einfügen?ich dachte, vielleicht so, aber so richtig klappts nicht:
HWND hChild; HINSTANCE test[4]; int g_iNumChild = 0; hChild = CreateWindowEx(WS_EX_MDICHILD,g_szChildClassName,"OpenGL window", WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,0,0,350,350, g_hMDIClient,NULL, test[g_iNumChild]=GetModuleHandle(NULL),&cs); g_iNumChild++;DANKE.
STICK.
-
Nur auf die Schnelle:
Wie schon gesagt: GetModuleHandle liefert das Handle des geforderten Moduls zurück. Diesen Wert hannst Du dann zwischenspeichern, z. B.
int Window[20]
...
Window[i] = GetModulHandle (NULL)
...Schau ruhig auch im MSDN nach.
-
man könnte da doch sicher auch mit SetWindowLong arbeiten, oder?
-
SERVUS.
Elektronix schrieb:
int Window[20]
...
Window[i] = GetModulHandle (NULL)wie stellst du dir eine umwandlung von einer INTEGER ZAHL in eine HINSTANCE vor? mein compiler macht da nicht mit.
(error C2440: '=' : 'struct HINSTANCE__ *' kann nicht in 'int' konvertiert werden)grüsse.
STICK.
-
Gibt denn der Aufruf der CALLBACK Funktion nicht schon das passende Handle genau fuer diese eine Instanz des Clients zurueck? Da muss nur noch fuer jede Instanz von diesem Client ein eigener Speicherbereich fuer die Dauer seines "Lebens" bereitgestellt werden.
(Wenn man also z.B. 5 VERSCHIDENE Clients vordefiniert, so kann man von jedem Client beliebig viele Instanzen zur Laufzeit erzeugen. Und jede (Instanz) soll unabhaengig von der anderen (Instanz) des gleichen Clients sein.
Wenn das so ist, dann funktioniert es so (fuer jede Client-Callback-Funktion):
global :
typedef struct tagMDDATA { stDISC stDisc; CSBAR sbMD; // CTABC tcMD; HWND hTab; // Handle des TabControl CREDIT reMD; } MDDATA, * PMDDATA;in WM_CREATE:
... // Platz für individuelle Daten pMDData = (PMDDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (MDDATA)); // Handle des Rahmen- und des Client-Fensters festhalten: hwndClient = GetParent (hwnd); hwndFrame = GetParent (hwndClient); // Statusbar erzeugen: SetWindowLong (hwnd, 0, (long) pMDData); pMDData->sbMD.Init (hwnd, NUM_FIELDS); // VARIANTE 1 //pMDData->hwndSBar = sbMD.Init (hwnd); // VARIANTE 2 // TabControl erzeugen: pMDData->hTab = pMDData->tcMD.Init (hwnd, NUM_TABS); // Ausgabefenster auf dem TabControl erzeugen: pMDData->reMD.Init (pMDData->hTab, 0); break;in WM_SIZE z.B.: so:
case WM_SIZE: pMDData = (PMDDATA) GetWindowLong (hwnd, 0); GetClientRect (hwnd, &rect); // Statusbar anzeigen: pMDData->sbMD.ScaleSBar (); // VARIANTE 1 pMDData->sbMD.WriteSBarField (0, TEXT("No disc")); pMDData->sbMD.WriteSBarField (1, TEXT("No track")); pMDData->sbMD.WriteSBarField (2, TEXT("mm:ss")); pMDData->sbMD.WriteSBarField (3, TEXT("Power OFF")); ...usw.
Sind hier nur Beispiele. Die Vorgehensweise hab' ich auch nur aus der MSDN - ist ganz gut beschrieben.
Blackbird
-
Hab' noch was vergessen:
case WM_DESTROY: pMDData = (PMDDATA) GetWindowLong (hwnd, 0); HeapFree (GetProcessHeap (), 0, pMDData);Die Types
CSBAR sbMD;
CTABC tcMD;
CREDIT reMD;sind Klassen, die alle Methoden fuer die Controls enthalten, z.B.: fuer die Statusbar
CSBAR::CSBAR (HWND hwnd, int iFields) { if (!hwnd) return; m_hwnd = hwnd; m_iFields = iFields; m_hwndSbar = InitSBar (); };Hier wird das Handle der Instanz (eines Clients) an die Statusbar uebergeben:
pMDData->sbMD.Init (hwnd, NUM_FIELDS); // VARIANTE 1Blackbird
-
[quote]wie stellst du dir eine umwandlung von einer INTEGER ZAHL in eine HINSTANCE vor? mein compiler macht da nicht mit. [/quote]
Hast Recht, war ein bißchen zu sehr aus dem Bauch geschossen
-
AN BLACKBIRD:
also ich muss leider sagen, dass ich nichts verstehe von dem, was du schreibst. hab auch irgendwie das gefühl, dass das nicht so zu meiner frage passt (?). weiss zum beispiel gar nicht, wozu ich WM_SIZE und so brauche und was die klassen der statusbar mit meinem problem zu tun haben.
mein problem ist einfach so, dass ich ein MAIN MDI WINDOW habe, mit ner TOOLBAR. wenn ich auf den button drücke, kommt ein OpenGL window, das ein CHILD WINDOW ist. in der CALLBACK FUNKTION für dieses child fenster steht, dass beim drücken von F1 eingezoomt wird. nun soll dieses zoomen aber immer nur beim aktiven fenster erfolgen, nicht bei allen OpenGl-fenstern. man müsste also auch irgendwie abfragen, welches fenster gerade aktiv ist.
DANKE schonmal, falls du noch irgendwelche ideen hast.
STICK.
-
Deine Callback-Funktion hat eine WM_CREATE case-Falle?
Wenn ja, dann muss dort das Handle (als Parameter HWND hwnd im Funktionsaufruf) dieser Instanz gespeichert werden. Und zwar in einem eigenen Speicherbereich:// Platz für individuelle Daten pMDData = (PMDDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (MDDATA));Die Struct pMMDDate ist hier nur Beispiel, sie kann auch aus nur einem Element (dem Handle) bestehen.
Mit
SetWindowLong (hwnd, 0, (long) pMDData); pMDData->sbMD.Init (hwnd, NUM_FIELDS); // VARIANTE 1wird das Handle gespeichert, hier fuer eine Statusbar. Dann nochmals fuer ein Tab-Feld und ein Edit-Fenster. Ist hier nur ein Beispiel. Das kannst Du natuerlich viel einfacher machen.
Einfach nur das Handle speichern.In Deinem Code in der case-Falle WM_COMMAND wird irgendwo die F1-Taste verarbeitet. Dort muss alles was Deine Instanz betrifft (zoomen), mit genau diesem Handle passieren. Und das holt man sich so, wie ich es in WM_SIZE gezeigt habe (zuerst die struct, darin ist das Handle):
case WM_SIZE: pMDData = (PMDDATA) GetWindowLong (hwnd, 0);Der restliche Code zeigt nur beispielhaft, wie es geht.
Den Speicherbereich immer freigeben, wenn die Instanz des Childs zerstoert wird.Blackbird
-
SERVUS.
habe in meinem programm folgendes hinzugefügt, klappt aber leider immer noch nicht. vielleicht kann jemand den grund für folgende fehlermeldung finden:
"error C2228: Der linke Teil von '.Init' muss eine Klasse/Struktur/Union sein"global:
typedef struct tagMDDATA { HWND hTab; } MDDATA, *PMDDATA;am anfang der Callbackfunktion habe ich folgende variable definiert:
PMDDATA pMDData;WM_CREATE:
pMDData = (PMDDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (MDDATA)); SetWindowLong (hWnd, 0, (long) pMDData); pMDData->hTab.Init (hWnd);WM_SIZE:
pMDData = (PMDDATA) GetWindowLong (hWnd, 0);WM_CLOSE:
pMDData = (PMDDATA) GetWindowLong (hWnd, 0); HeapFree (GetProcessHeap (), 0, pMDData);DANKE schonmal.
STICK.
-
Du weißt inzwischen, ich bin auch Anfänger
Aber hast Du es schon mal mit
cbWndExtra versucht?[quote]
Specifies the number of extra bytes to allocate following the window instance. The operating system initializes the bytes to zero. If an application uses the WNDCLASS structure to register a dialog box created by using the CLASS directive in the resource file, it must set this member to DLGWINDOWEXTRA. [/quote]
Also, den Status des Fensters in WndClassExtra speichern... ist halt so ne Idee...
-
Statt
pMDData->hTab.Init (hWnd);einfach nur
pMDData->hTab = hWnd;Weil: Deine Struct MDData enthaelt keine Klasse (wie in meinem Beispiel), sondern nur das Handle.
Und wenn die F1-Taste verarbeitet wird, musst Du das gespeicherte Handle auch verwenden:
case WM_KEYDOWN: pMDData = (PMDDATA) GetWindowLong (hWnd, 0); if (pMDData->hTab == (HWND)lParam && VK_F1 == wParam) { MessageBox (pMDData->hTab, "F1 down", "Eingabebox", MB_OK); // nur Beispiel! } ...Wo die F1-Taste abgefangen wird; das kann bei Dir auch anders aussehen.
Blackbird
-
SERVUS BLACKBIRD.
danke für die antwort. ich werde deine hinweise mit einbauen und sag dann bescheid, ob alles funktioniert hat.
STICK.
-
HALLO.
ich hatte vor einer weile (23.01.2006) dieses problem mit MDI und verschiedenen CALLBACK FUNKTIONEN gepostet.
leider bin ich seit dem nicht mehr dazu gekommen, das zu ende zu bringen. darum wollte ich jetzt noch einmal nachfragen, ob mir noch jemand helfen kann??

ich habe immer noch das problem, dass ich nicht weis, wie ich das gespeicherte HANDLE für meine verschiedenen CALLBACK FUNKTIONEN wieder verwenden kann. ich habe es jetzt am beispiel der F1 taste so gemacht, aber wenn ich F1 betätige, dann stürzt das program ab.
case WM_KEYDOWN: { pMDData = (PMDDATA) GetWindowLong (hWnd, 0); if (pMDData->hTab == (HWND)lParam && PAD[wParam] == TRUE) MessageBox (pMDData->hTab, "F1 down", "Eingabebox", MB_OK); return 0; }DANKE.

STICK.
-
An welcher Stelle genau stürzt er denn ab?
-
das programm macht nicht mehr weiter, wenn ich auf F1 drücke.
STICK.

-
PAD[wParam]das dürfte in einen Speicherbereich zeigen, der nicht zu Deinem Prozess gehört.
Blackbird
-
Du drückst dich nicht gerade präzise aus. Wie genau sieht der Fehler aus? Zugriffsverletzung? Wenn ja, wo tritt diese auf (in welcher Zeile)?
-
ja. hast ja recht, damit kann man als aussenstehender ohne quellcode vor augen nicht viel anfangen. darum hier jetzt mehr informationen:
fehlermeldung:
unbehandelte ausnahme in api6.exe: 0*C000000005 access violation
an folgender stelle:
if (pMDData->hTab == (HWND)lParam && PAD[wParam] == TRUE)
dazu muss ich aber sagen, dass ich zuvor, also bevor ich die callbackfunktion angenfangen habe zu verändern für viele childwindows, folgenden code hatte und da gab es keine access violation meldung bei F1 betätigung. soll heissen, dass es da keine problem mit dem speicherzugriff geben müsste.
case WM_KEYDOWN: { PAD[wParam] == TRUE; return 0; }okay. lasst mich bitte wissen, wenn ihr noch mehr infos zu meinem code braucht.
DANKE!STICK

-
Hast du mal pMDData->hTab == (HWND)lParam oder PAD[wParam] == TRUE weggelassen`- dann sollte ja zumindest in einem Fall die Fehlermeldung ja weg sein.
PAD[wParam] == TRUE;Was soll das tun
