 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 06.01.2010, 00:21 Titel: Rechtsklick auf Checkbox ermöglichen (MFC/WinAPI) |
|
|
Hi,
da es hier primär um C++ geht, poste ich mal im Computer-Forum. Ich habe eine Checkbox auf einem Dialog und möchte nun auch den Rechtsklick (und später auch Mittellklick) auf diese abfragen. In VB ging das ja recht einfach, aber die MFC-Komponenten scheinen sowas nicht zu bieten. Deswegen versuche ich jetzt irgendwie, den Rechtsklick selbst abzufangen und auszuwerten. Das ON_WM_RBUTTONDOWN-Event trifft leider nur ein, wenn ich direkt auf das Fenster einen Rechtsklick mache, ein Rechtsklick auf Kindelemente wird da nicht registriert.
Weiß jemand, wie ich solche Events mit der WinAPI oder MFC auswerten kann? Oder hat jemand lust, den Code nacht Qt zu portieren?  _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.

Zuletzt bearbeitet von Jojo am 06.01.2010, 18:39, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Sebastian Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
|
|
Nach oben |
|
 |
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 06.01.2010, 01:21 Titel: |
|
|
Wenn ich wüsste um was es geht würde ichs mir aufjedenfall anschauen.
Aus Sebastians Beitrag schließe ich das es viel ist.
Aber grundsätzlich sinnvoll, nicht jeder hat MFC. |
|
Nach oben |
|
 |
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 06.01.2010, 01:25 Titel: |
|
|
Wenn auch Winapi geht:
Du nimmst dir mit GetClassLongPtr den Zeiger auf die Windowfunktion der Checkbox und speicherst diesen.
Dann fügst du den Zeiger auf eine eigene Windowfunktion mit SetClassLongPtr ein.
Diese wertet dann WM_RBUTTONDOWN aus.
Wenn eine andere Nachricht als WM_RBUTTONDOWN reinkommt gibst du die einfach an die originale Windowfunktion weiter, deren Zeiger du ja gespeichert hast.
Zuletzt bearbeitet von Stueber am 06.01.2010, 02:22, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 06.01.2010, 02:15 Titel: |
|
|
Hier das Beispiel:
Code: | #include "windows.bi"
dim shared func_pointer as function(byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
function WndProc ( byval hWnd as HWND, _
byval wMsg as UINT, _
byval wParam as WPARAM, _
byval lParam as LPARAM ) as LRESULT
function = 0
select case( wMsg )
case WM_CREATE
exit function
case WM_DESTROY
PostQuitMessage( 0 )
exit function
end select
function = DefWindowProc( hWnd, wMsg, wParam, lParam )
end function
function WndProc_Check ( byval hWnd as HWND, _
byval wMsg as UINT, _
byval wParam as WPARAM, _
byval lParam as LPARAM ) as LRESULT
if wMsg = WM_RBUTTONDOWN then
MessageBox(0,"Checkbox wurde geklickt mit der rechten Maustaste!","Nachricht!",MB_OK)
end if
function = func_pointer( hWnd, wMsg, wParam, lParam )
end function
dim wMsg as MSG
dim wcls as WNDCLASS
dim hInstance as HINSTANCE
dim hPrevInstance as HINSTANCE
dim szCmdLine as string
dim iCmdShow as integer
hInstance = GetModuleHandle(null)
hPrevInstance = 0
szCmdLine = command()
iCmdShow = SW_NORMAL
with wcls
.style = CS_HREDRAW or CS_VREDRAW
.lpfnWndProc = @WndProc
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = hInstance
.hIcon = LoadIcon(NULL, IDI_APPLICATION)
.hCursor = LoadCursor(NULL, IDC_ARROW)
.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))
.lpszMenuName = NULL
.lpszClassName = @"Fenster"
end with
if(RegisterClass(@wcls) = FALSE) then
MessageBox(null, "Die Fensterklasse konnte nicht registriert werden.", "Fehler", MB_ICONERROR)
end
end if
dim as HWND h = CreateWindowEx(0, @"Fenster", "TEST", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 200,100, NULL, NULL, GetModuleHandle(null), NULL)
dim as HWND c = CreateWindowEx(0, @"BUTTON", "Checkbox", WS_CHILD or WS_VISIBLE or BS_AUTOCHECKBOX,10, 10, 85, 40, h, NULL, GetModuleHandle(null), NULL)
func_pointer = GetWindowLongPtr(c,GWL_WNDPROC)
SetWindowLongPtr(c,GWL_WNDPROC,cast(DWORD,@WndProc_Check))
ShowWindow(h,SW_SHOW)
UpdateWindow(h)
while( GetMessage(@wMsg, NULL, 0, 0) <> FALSE)
TranslateMessage(@wMsg)
DispatchMessage(@wMsg)
wend |
Oder in C++ als Unicode Version:
Code: | #include <windows.h>
LRESULT (*func_pointer)(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc ( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
switch( wMsg )
{
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, wMsg, wParam, lParam );
}
LRESULT WndProc_Check ( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
if (wMsg == WM_RBUTTONDOWN)
{
MessageBox(0,L"Checkbox wurde geklickt mit der rechten Maustaste!",L"Nachricht!",MB_OK);
}
return func_pointer( hWnd, wMsg, wParam, lParam );
}
int main(int argc, char *argv[])
{
MSG wMsg ;
WNDCLASS wcls;
HINSTANCE hInstance;
HINSTANCE hPrevInstance;
hInstance = GetModuleHandle(0);
hPrevInstance = 0;
wcls.style = CS_HREDRAW | CS_VREDRAW;
wcls.lpfnWndProc = &WndProc;
wcls.cbClsExtra = 0;
wcls.cbWndExtra = 0;
wcls.hInstance = hInstance;
wcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wcls.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
wcls.lpszMenuName = NULL;
wcls.lpszClassName = L"Fenster";
if(RegisterClass(&wcls) == FALSE)
{
MessageBox(0, L"Die Fensterklasse konnte nicht registriert werden.", L"Fehler", MB_ICONERROR);
return 1;
}
HWND h = CreateWindowEx(0, L"Fenster", L"TEST", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 200,100, NULL, NULL, GetModuleHandle(0), NULL);
HWND c = CreateWindowEx(0, L"BUTTON", L"Checkbox", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,10, 10, 85, 40, h, NULL, GetModuleHandle(0), NULL);
func_pointer = (LRESULT(*)(HWND,UINT,WPARAM,LPARAM))GetWindowLongPtr(c,GWL_WNDPROC);
SetWindowLongPtr(c,GWL_WNDPROC,(DWORD)WndProc_Check);
ShowWindow(h,SW_SHOW);
UpdateWindow(h);
while( GetMessage(&wMsg, NULL, 0, 0) != FALSE)
{
TranslateMessage(&wMsg);
DispatchMessage(&wMsg);
}
return 0;
}
|
Du brauchst nur den HWND der Checkbox, dann kannst du es auch so machen. |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 06.01.2010, 11:44 Titel: |
|
|
Danke, das werde ich heute abend mal ausprobieren.
Und ja, es geht um den ModPlug und ja, es ist viel Arbeit (auch wenn ModPlug wesentlich mehr als nur die GUI ist). Aber je mehr mitmachen, desto weniger ist es für jeden und im Moment wären wir wohl 3-4 Leute, die den Code umbauen können/wollen. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 06.01.2010, 21:37 Titel: |
|
|
Ich habe mir jetzt den Thread nicht durchgelesen, aber Subclassing wäre denke ich die beste Möglichkeit das zu realisieren.
//Lol sehe gerade, dass Stueber das schon geschrieben hat (Themenüberblick) |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 08.01.2010, 20:33 Titel: |
|
|
Hmm, so ganz funktioniert das noch nicht. Den nötigen Code habe ich mal übernommen, aber in der Zeile "return func_pointer( hWnd, wMsg, wParam, lParam );" gibt's ne access violation... Habe im Code ein paar Sachen geändert (das muss LONG_PTR sein, nicht DWORD), aber auch unmodifiziert tritt der Fehler auf...
Code: | HWND c = GetDlgItem(m_nCleanupIDtoDlgID[CU_REMOVE_INSTRUMENTS])->m_hWnd;
func_pointer = (LRESULT(*)(HWND,UINT,WPARAM,LPARAM))GetWindowLongPtr(c, GWLP_WNDPROC);
SetWindowLongPtr(c, GWLP_WNDPROC, (LONG_PTR)WndProc_Check);
|
Der pointer is auch nicht 0...
Mal weitersuchen... _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 08.01.2010, 21:25 Titel: |
|
|
Hast du den Pointer auf Null beim Setzen oder vor dem Aufruf geprüft? |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 08.01.2010, 21:28 Titel: |
|
|
Der Pointer änder sich doch nicht von selbst... Und nein, er war in keinem von beiden Fällen null. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 09.01.2010, 16:28 Titel: |
|
|
Naja das kommt ganz auf den Stil an
Wenn man bei einem Vergleich die Konstante rechts schreibt, und statt einem doppelten Gleichzeichen nur ein einfaches verwendet, setzt man die Variable auf diesem Wert. Beim GCC muss man explizit Warnungen bei Wertzuweisungen in if-Statements aktivieren. (Ich weiß nicht, ob der VC++ Compiler von sich aus derartige Warnungen generiert). Deswegen habe ich es mir angewöhnt die Konstante links zu schreiben, denn eine Wertzuweisung an eine Konstante produziert logischerweise einen Fehler.
B2T
Installiere mal OllyDbg und schau mal nach, wohin der Zeiger denn zeigt. Tritt der Fehler nur außerhalb oder nur innerhalb der IDE auf? Oder immer? |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 09.01.2010, 16:51 Titel: |
|
|
mal so nebenbei... der pointer fängt immer mit ffff an. könnte das was bedeuten?
btw, ich mache ja keine vergleiche/zuweisungen, ich setz nen breakpoint und schaue mir dann die variable an  _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 09.01.2010, 18:28 Titel: |
|
|
Der Pointer dürfte mit hoher Wahrscheinlichkeit nur dann mit 0xFFFF beginnen, wenn du das Programm in der IDE ausführst. VS dreht da irgendwas mit dem Speicher rum... |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|