Property Sheet: Ich werd noch wahnsinnig!!!!!!
-
Hi,
hab ja (wie vielleicht schon aus anderem Thread bekannt
), "versucht" eine Property Sheet in mein Programm einzubinden.
Damals kam kein PSN_APPLY an.
Da hab ich das Flag "PSH_MODELESS" beim Erzeugen des Property sheets weggelassen und so eine modales Property sheet erzeugt.
Ich hab drei Pages, in einer Page Dialog Prozedur hab ich folgenden Code:LRESULT CALLBACK EditorShortcutProc(HWND Hwnd, UINT nMessage, WPARAM WParam LPARAM LParam) { switch (nMessage) { case WM_NOTIFY: { LPPSHNOTIFY pstNotify = (LPPSHNOTIFY) LParam; if (pstNotify->hdr.code == PSN_KILLACTIVE) { fprintf(Protokoll, "Killactive\n"); SetLastError(0); if (!SetWindowLong(pstNotify->hdr.hwndFrom, DWL_MSGRESULT, TRUE)) { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION); LocalFree(lpMsgBuf); } return FALSE; // wenn hier TRUE steht ändert sich nichts } if (pstNotify->hdr.code == PSN_APPLY) { fprintf(Protokoll, "Apply\n"); return PSNRET_NOERROR; } if (pstNotify->hdr.code == PSN_QUERYCANCEL) { fprintf(Protokoll, "Reset\n"); } } default: break; } return false; }
Ich geb also bei PSN_KILLACTIVE mit SetWindowLong() TRUE zurück (schlägt nicht fehl) und in der MSDN steht, dass dann die Property Sheet noch angezeigt werden müsste, außerdem würde nur PSN_APPLY gesendet, wenn man FALSE zurückgeben würde.
Nun krieg ich aber immer PSN_APPLY, egal, was ich mit SetWindowLong() zurückgebe!
Also ich weiß nicht, aber Property Sheets sind doch wahrscheinlich das Dümmste, was es gibt!
Ich denke mal, wenn man OK klickt und in PSN_KILLACTIVE mit SetWindowLong() FALSE returnt, schließt sich das Property sheet, wenn man aber auf "Übernehmen" klickt, bleibt sie weiterhin aktiv.
Wenn ich aber Übernehmen klicke, stürzt mein Programm mal eben schnell ab!
Falls irgendjemand schonmal was mit Property Sheets erreicht hat, kann er mir ja mal bescheid sagen!
-
Wenn Du in PSN_KILLACTIVE TRUE zurückgibst, steht das für einen Fehlschlag. Du bekommst dann PSN_APPLY nicht mehr gesendet. Das funktioniert aber nur, wenn Deine DialogProc TRUE zurückgibt und nicht, wie bei Dir, FALSE.
Außerdem prüfst Du die Rückgabe von SetWindowLong. Da kommt der zuvor eingesetzte Wert für DWL_MSGRESULT zurück. Ich könnte wetten, daß das immer 0 ist (jedenfalls an dieser Stelle). Um sicher zu sein, daß es ein Fehlschlag war, mußt Du nachträglich den ErrorCode mit GetLastError prüfen. Das Zurücksetzen des ErrorCodes vor dem Funktions-Aufruf machst Du ja schon.
In PSN_APPLY gibst Du den Wert direkt zurück. Das ist so nicht richtig. Du mußt auch hier SetWindowLong bemühen und Dich mit TRUE aus der DlgProc verabschieden.
-
hab es jetzt also so gemacht (ich denke, so hast dus gemeint):
case PSN_KILLACTIVE: { fprintf(Protokoll, "Killactive\n"); SetWindowLong(Hwnd, DWL_MSGRESULT, FALSE); return TRUE; } break; case PSN_APPLY: { fprintf(Protokoll, "Apply.\n"); SetWindowLong(Hwnd, DWL_MSGRESULT, PSNRET_NOERROR); return TRUE; } break;
Nun ist es aber so, dass wenn ich bei PSN_KILLACTIVE statt FALSE mit SetWindowLong TRUE zurückgeb, kommt auch PSN_APPLY.
Wie dem auch sei: Was eigentlich wichtig ist: Wie kann ich denn nun entscheiden, ob OK oder Übernehmen geklickt wurde? Wenn ich in bisherigen Versuchen "Übernehmen" geklickt hatte, wurde die Box einfach geschlossen, sollte doch eigentlich noch geöffnet bleiben. Muss ich da was machen oder ist das normalerweise standardmäßig der Fall?
-
JensE schrieb:
Muss ich da was machen oder ist das normalerweise standardmäßig der Fall?
Das hört sich sehr nach einem vergessenen break (oder ähnlichem) an. Der von Dir gezeigte Code lässt jedenfalls nichts erkennen. Auch darfst Du nicht PSN_APPLY bekommen, wenn Du PSN_KILLACTIVE abbrichst! Du hast da irgendwo noch einen richtig fetten Bock sitzen.