Jak sprawdzić który przycisk został kliknięty?

0

Witam.
Mam jakiś tam przycisk utworzony i chciałbym sprawdzić w kodzie poniżej który przycisk został kliknięty(i ogólnie co warto wiedzieć o tym switch(uMsg)).
Rozumiem, że wszystkie funkcje są uruchammiane w tym switch()?
Czy to nie jest język proceduralny?

switch (uMsg)
    {
    case WM_DESTROY:
        fclose(plik);
        PostQuitMessage(0);
        return 0;
    case WM_LBUTTONDOWN:
        MessageBox(hwnd, L"msg", L"title", MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
        return 0;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // All painting occurs here, between BeginPaint and EndPaint.

        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }
0

Google: WM_LBUTTONDOWN
Google: SendMessage

0

Microsoft zmonopolizował pomoc do VS C++ i zrobił to mega nieudolny sposób (rozumiem, że chce pościągać ludzi na swoje kursy). Myślisz, że nie próbowałem szukać?

0

Na 100% nie próbowałeś, pod tymi hasłami jest masz jako pierwszy (w obu przypadkach)

0

Wielkię dzięki za tych pare linijek.
Po co zaśmiecasz forum jak nie masz nic do napisania?
Jak takiej prostej rzeczy się nie można doprosić to po co to forum jest? Żeby odsyłać do googla?
Rozumiem, że za kasę byś coś podpowiedział.

case WM_COMMAND:
        {

        if ((HWND)lParam == hwndButton) { //hwndButton - uchwyt do okna
            MessageBox(
                NULL,
                (LPCWSTR)L"Resource not available\nDo you want to try again?",
                (LPCWSTR)L"Account Details",
                MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2
            );
        }
0

Okno klasy BUTTON nie reaguje na kliknięcie innym przyciskiem niż podstawowy przycisk myszy, więc też nie podaje w notyfikacji BN_CLICKED (wiadomości WM_COMMAND), którym przyciskiem myszy kliknięto.
Klasa BUTTON ma własną procedurę okna, więc nie wysyła bezpośrednio zdarzeń do procedury okna nadrzędnego, której fragmenty załączyłeś.
Może napisz, do czego potrzebne jest wiedzieć, który przycisk myszy został naciśnięty na oknie systemowej klasy BUTTON, skoro to okno ignoruje takie kliknięcie.

1
johnny_Be_good napisał(a):

... (i ogólnie co warto wiedzieć o tym switch(uMsg)).
... Czy to nie jest język proceduralny?

Poszukałbym bym przykładów od poziomu ZERO, bo bez chodzenia ciężko zacząć biegać .

1

Swoją droga po co się męczysz tym niskopoziomowym API z lat 90tych?
Jest dużo bardziej przyjemnych rozwiązań do obsługi okienek, w tym tych od MS.

0

@MarekR22: - "Manna się katował i lubi C, ja też się katowałem i też lubię C nie wiem kto nie lubi C. — CloudPro 2023-01-27 20:01"
No ja znajduję przyjemność w katowaniu się tym.

1

W systemie Windows mamy dwa rodzaje kontrolek.
Kontrolki "starego" typu (istniały od początku systemu): Edit, Button, ComboBox, ListBox, Static.
Kontrolki "nowego" typu - wprowadzone w Win95 i później: ListView, TreeView, itd.

Wszystkie kontrolki wysyłają powiadomienia do swoich rodziców.
Kontrolki starego typu przesyłają powiadomienia poprzez WM_COMMAND.
(HIWORD)wParam jest kodem powiadomienia.
np. BN_CLICKED - to jest powiadomienie o klikniętym przycisku
LBN_SELCHANGE - powiadomienie o zmiania pozycji w liście, itd.
(LOWORD)wParam - jest identyfikatorem kontrolki, lParam zawiera uchwyt do kontrolki.

Kontrolki nowego typu przesyłają powiadomienia do rodzica przez komunikat WM_NOTIFY.
lParam zawiera adres do struktury NMHDR, której pole code zawiera kod powiadomienia.
np. LVN_ITEMCHANGED, TVN_ITEMEXPANDING
Za nagłówkiem NMHDR znajduje się struktura o polach zależnych od typu kontrolki, która zawiera informacje właściwe dla danego powiadomienia.

Wszystkie kontrolki da się subklasować, ale ma to sens, jeśli chcemy dodać (lub zmienić) jakąś funkcjonalność.
Jeśli funkcjonalność kontrolki jest wystarczająca, to da się ją obsłużyć bez subklasowania.

0

Tak próbowałem (HIWORD)wParam - i to NIE DZIAŁA. Działa HIWORD(wParam) - też myślałem że 666 się pomylił, ale miał rację to jest HIWORD(wParam). Domyślam się, że LOWORD też tak działa.

Jak mi podpowiedział, że ListBox musi mieć przy utworzeniu parametr stylu LBM_NOTIFY to zażartowałem, że do editBox też może powinienem dodać style KBD_NOTIFY (takie mam poczucie humoru), ale no to LBM_NOTIFY zadziałało.
Wiesz, lepiej by mi było operować na tym jak byś pisał jakiego typu są to struktury wParam się okazał byc HIWORD, i dopiero jak to tak rzutowałem to zadziałało.

LVN_ITEMCHANGED - to jest komunikat ale jakiego typu?
No nie ukrywam problem cały czas jest z obslużeniem klawisza enter i escape (nie wiem czy jakiekolwiek inne działają).
Bym potestował ale cały mój główny projekt się zawiesił (nie można zapisać do pliku i skompilować kompilator krzyczy, a potem usunąłem plik LOCK w katalogu projektu to teraz nie wiem co będzie).
Kopiowanie zawartości do nowego projektu zatrzymało się na etapie takim, że mi kompilator nie podświetla utworzonych uchwytów do okien na niebiesko, i nie wyświetla tych kontrolek w oknie głównym.

"Jeśli funkcjonalność kontrolki jest wystarczająca, to da się ją obsłużyć bez subklasowania." - no mi chodzi o to, żeby po naciśnięciu klawisza enter kontrolka się urkyła.

1

Musisz mieć zawsze świadomość z jakiego typu kontrolką masz do czynienia (nową, czy starą) i w zależności od tego, albo sprawdzać powiadomienia przez WM_COMMAND, albo przez WM_NOTIFY. Te komunikaty, który mają w nazwie N - to są powiadomienia (one przychodzą od kontrolki do okna rodzica). Te które mają w nazwie M - to są komunikaty wysyłane do kontrolki. Z kolei litera S w nazwie - oznacza style.
Czyli nie będzie LBM_NOTIFY, tylko LBS_NOTIFY.
LVN_ITEMCHANGED - to komunikat powiadamiający, który przychodzi z kontrolki do okna. LV oznacza ListView. Ten komunikat przyjdzie do okna w postaci WM_NOTIFY (podałem go jako przykład).

Jeśli chodzi o obsługę klawiatury, to sytuacja jest nieco bardziej skomplikowana niż obsługa innych zdarzeń. Jest tak dlatego, że w systemie jest jedna klawiatura, a wiele okienek. System musi wiedzieć, do którego okienka ma skierować informacje z klawiatury. Dlatego wymyślono "focus". To okno, które ma focus odbierze informację z klawiatury.
Zauważ, że jeżeli focus jest w Twojej kontrolce edycyjne, to komunikaty z klawiatury są przesyłane do niej i wewnątrz niej są obsługiwane.
Ponadto mamy przynajmniej trzy rodzaje okien: okno zwykłe (najczęściej główne okno aplikacji), okno dialogowe modalne i okno dialogowe niemodalne.
W przypadku okna głównego podstawowym sposobem obsługi zdarzeń klawiatury jest TranslateMessage() umieszczony w głównej pętli komunikatów.
Oczywiście można łapać komunikaty z klawiatury (WM_KEYDOWN, itp.), ale to w dużym programie ma średni sens (okno ma zazwyczaj menu, chcemy, żeby to menu też mogło być obsługiwane z klawiatury, ponadto chcemy, żeby działały systemowe skróty klawiaturowe, itd.).
Jeśli chodzi o kontrolki, to one zazwyczaj są umieszczane wewnątrz okien dialogowych. Wtedy ich obsługa za pomocą klawiatury jest inna niż w oknie głównym. W oknach dialogowych niemodalnych, w pętli głównej programu należy umieścić funkcję IsDialogMessage i za jej pomocą przechwycić te kombinacje klawiszy, które chcemy obsłużyć i w zależności od tego, czy obsłużyliśmy czy nie, zwracamy prawdę lub fałsz.
W oknach dialogowych modalnych, skróty klawiszowe definiuje się w zasobach programu. Można to oczywiście programowo przechwytywać i zmieniać, ale nie zalecam tego (po oknie dialogowym można "chodzić" klawiszem Tab, klawisz Esc zamyka okno, a Enter działa na przycisk domyślny, więc łatwo tu sprawę przekombinować).

To tytułem wprowadzenia. Odpowiadając na Twój konkretny problem - Twoje okno będzie inaczej zachowywało się na Enter w zależności od tego, czy kontrolka ma focus, czy nie (tzn. czy w Twojej kontrolce jest aktywny kursor). Nie mam w tej chwili uruchomionego Twojego programu, więc trudno mi odpowiedzieć na sto procent, jakie komunikaty przyjdą, ale wydaje mi się, że będzie tak, że jeśli kontrolka nie będzie aktywna (nie będzie w niej kursora), to Enter spowoduje przyjście komunikatu WM_KEYDOWN z kodem 13. Jeśli kursor będzie w kontrolce aktywny, to działanie będzie różne w zależności od tego, czy kontrolka ma styl ES_WANTRETURN oraz styl ES_MULTILINE. Jeśli jest ES_MULTILINE i jest ES_WANTRETURN, to Enter spowoduje utworzenie nowego akapitu w tej kontrolce.
W przeciwnym wypadku Enter wewnątrz kontrolki edycyjnej przesyła powiadomienie do okna dialogowego (w którym ta kontrolka się znajduje) o tym, że chcemy zamknąć okno.
Ponieważ Ty nie masz tej kontrolki w oknie dialogowym, tylko w zwykłym oknie, więc nie jestem pewien jak to zadziała. Możesz sprawdzić czy IsDialogMessage umieszczony wewnątrz głównej pętli komunikatów odbierze WM_COMMAND z kodem IDOK (być może tak, trzeba to sprawdzić).
Jeśli to nie zadziała, to w takim rozwiązaniu trzeba subklasować kontrolkę i tam przechwycić WM_KEYDOWN.

0

"Zauważ, że jeżeli focus jest w Twojej kontrolce edycyjne, to komunikaty z klawiatury są przesyłane do niej i wewnątrz niej są obsługiwane." - chodzi o editBox, czyli jednak subklasowanie?

Subklasowałem już jedną funkcję no i to zadziałało (bo miało wyświetlić komunikat i wyświetliło).

", że jeśli kontrolka nie będzie aktywna (nie będzie w niej kursora), to Enter spowoduje przyjście komunikatu WM_KEYDOWN z kodem 13" - ale editbox zawsze będzie aktywna kiedy będę oczekiwał sprawdzenia enter.

"w którym ta kontrolka się znajduje) o tym, że chcemy zamknąć okno." - ja chcę zamienić to zamknięcie okna na jego ukrycie.

A tak ogólnie, to jestem już poza etapem instrukcji switch() - poza nią są jakby większe możliwości

Jak klikam przycisk tego to słyszę jedynie beeeep.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if ((HWND)lParam == hEdit3) {
        if (message == WM_NOTIFY && HIWORD(wParam) == IDOK) {
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            
            ShowWindow(hEdit3, SW_HIDE);
        }
    }

Zaczynam od początku.
Robię int hw_wParam hw_lParam, hw_wParam, lw_lParam;
zamienię to na stringi i wrzucę do innego editBox żeby zobaczyć co się dzieje.
Wszystkie zdarzenia tak zrobię.

Klikam na edit'a i coś takiego mi wyświetla.
Ale entera nie łapie, tylko beep.

message: 273 
| lParam: 2491682 | wParam: 33554432 | LOWORD(lParam): 1314 | HIWORD(lParam): 38 

Poniżej cały czas się uruchamia na starcie programu - edit jest ukryty(wziąłem to z dodanego przez firmę okienka About).

  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
                ShowWindow(hEdit3, SW_HIDE);
            }

Czy nie powinienem w kontrolce edit przekazać coś takiego

EndDialog(hDlg, LOWORD(wParam));

?

0

Ok trochę to zaczyna działać, wczytuje text a po kliknięciu enter albo escape się zamyka, tak jak pisaliście, subklasowane już od początku.

Dobra mam taki wpis w pliku "WindowsProject11.rc"

/////////////////////////////////////////////////////////////////////////////
//
// Okno dialogowe
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Informacje WindowsProject11"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "WindowsProject11, Wersja 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (c) 2023",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
    EDITTEXT        199, 0, 0, 200, 200,    // mój autorski dodatek

END

/////////////////////////////////////////////////////////////////////////////

Pętla tego to:

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Pytanie, jak to dynamicznie modyfikować to okienko?

Bo będę potrzebował, żeby ono pełniło różne funkcje.

0

Poniżej zamieszczam działający kod przykładowego okna dialogowego.
Są w nim stare kontrolki (listbox, edit i button, oraz nowa kontrolka - treeView).
To jest w starym Borlandzie, więc być może kod będzie wymagał drobnego dopasowania do Twojego kompilatora.
Popatrz jak są obsługiwane powiadomienia dla różnych typów kontrolek.

#include <windows.h>
#include <commctrl.h>
#include "dialog.rh"

BOOL CALLBACK DialogProc(HWND hwndDlg,	UINT uMsg, WPARAM wParam,  LPARAM lParam){
	switch(uMsg){
		case WM_INITDIALOG:{
			//Tu ustawić stan początkowy kontrolek
			SendDlgItemMessage(hwndDlg, IDC_LISTBOX1, LB_ADDSTRING, 0, (LPARAM)"Test1");
			SendDlgItemMessage(hwndDlg, IDC_LISTBOX1, LB_ADDSTRING, 0, (LPARAM)"Test2");
			TV_INSERTSTRUCT tv;
			tv.hParent=NULL;
			tv.hInsertAfter=TVI_FIRST;
			tv.item.mask=TVIF_TEXT;
			tv.item.pszText="ROOT";
			HTREEITEM root=TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_LISTBOX2), &tv);
			tv.hParent=root;
			tv.item.pszText="Dziecko 1";
			TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_LISTBOX2), &tv);
			tv.item.pszText="Dziecko 2";
			TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_LISTBOX2), &tv);
			tv.item.pszText="Dziecko 3";
			TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_LISTBOX2), &tv);
			TreeView_Expand(GetDlgItem(hwndDlg, IDC_LISTBOX2), root, TVE_EXPAND);
		}
			break;
		case WM_NOTIFY:{//obsługa powiadomień dla kontrolek nowego typu
			NMHDR* hdr=(NMHDR*)lParam;
			switch(hdr->idFrom){
				case IDC_LISTBOX2:
					switch(hdr->code){
						case TVN_SELCHANGED:{//zmiana wybranej pozycji
							NM_TREEVIEW* item=(NM_TREEVIEW*)lParam;
							//item zawiera informacje o zmienianych pozycjach
							SetDlgItemText(hwndDlg, IDC_STATIC1, "TreeView zmieniło wybrana pozycję");
						}
							break;
						case NM_KILLFOCUS://treeView utraciło focus
							SetDlgItemText(hwndDlg, IDC_STATIC1, "treeView utraciło focus");
					}
				break;
			}
		}
			break;
		case WM_COMMAND://obsługa powiadomień dla kontrolek starego typu
			switch(LOWORD(wParam)){
				case IDC_EDIT1:
					switch(HIWORD(wParam)){
						case EN_KILLFOCUS:
							//Pole pierwsze utraciło focus
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Pole pierwsze utraciło focus");
						break;
					}
					break;
				case IDC_EDIT2:
					switch(HIWORD(wParam)){
						case EN_KILLFOCUS:
							//Pole drugie utraciło focus
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Pole drugie utraciło focus");
						break;
					}
					break;
				case IDC_LISTBOX1:
					switch(HIWORD(wParam)){
						case LBN_SELCHANGE:
							//Lista zmeniła wybrana pozycję
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Lista zmeniła wybrana pozycję");
						break;
						case LBN_KILLFOCUS:
							//Lista utracila focus
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Lista utraciła focus");
						break;
					}
					break;
				case IDOK:
					//zamknięcie z kodem IDOK
					//tu zatwierdzić wprowadzone zmiany
						EndDialog(hwndDlg, IDOK);
					break;
				case IDCANCEL:
					//zamknięcie z kodem IDCANCEL
					//tu odwołać wprowadzone zmiany
						EndDialog(hwndDlg, IDCANCEL);
					break;
				case IDC_PUSHBUTTON1:
					switch(HIWORD(wParam)){
						case BN_CLICKED:
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Kliknięty przycisk");
							break;
						case BN_KILLFOCUS:
							SetDlgItemText(hwndDlg, IDC_STATIC1, "Przycisk stracił focus");
							break;
					}
					break;
			}
	}
	return (BOOL)FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){
	InitCommonControls();
	int retCode=DialogBox(hInstance, MAKEINTRESOURCE(DIALOG_1), NULL, (DLGPROC)DialogProc);
	if(retCode==IDOK){
		MessageBox(NULL, "Zamknięty dialog z kodem OK", "TEST", MB_OK);
		//Tu zaktualizowac stan progreamu po zamkniętym dialogu z kodem IDOK
	}
	return TRUE;
}
/****************************************************************************
DIALOG.RC
produced by Borland Resource Workshop
*****************************************************************************/
#include "dialog.rh"
#define BS_NOTIFY 0x00004000L

DIALOG_1 DIALOG 6, 15, 207, 160
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "DIALOG_1"
FONT 8, "MS Sans Serif"
{
 DEFPUSHBUTTON "OK", IDOK, 148, 116, 50, 14
 PUSHBUTTON "Cancel", IDCANCEL, 148, 134, 50, 14
 PUSHBUTTON "Button", IDC_PUSHBUTTON1, 14, 129, 50, 14, BS_NOTIFY
 LISTBOX IDC_LISTBOX1, 14, 53, 49, 59, LBS_STANDARD
 CONTROL "", IDC_LISTBOX2, "SysTreeView32", WS_BORDER|WS_CHILD | WS_VISIBLE | WS_TABSTOP, 83, 52, 49, 58
 EDITTEXT IDC_EDIT1, 153, 58, 41, 12, WS_BORDER | WS_TABSTOP
 EDITTEXT IDC_EDIT2, 153, 78, 41, 12, WS_BORDER | WS_TABSTOP
 LTEXT "", IDC_STATIC1, 14, 11, 167, 12
}
/****************************************************************************
dialog.rh
produced by Borland Resource Workshop
*****************************************************************************/

#define DIALOG_1			1
#define IDC_PUSHBUTTON1		101
#define IDC_LISTBOX1		102
#define IDC_LISTBOX2		103
#define IDC_EDIT1			104
#define IDC_EDIT2			105
#define IDC_STATIC1 		106

Jeśli dialog ma pełnić różne funkcje, to w zasobach dajesz wszystkie możliwe kombinacje kontrolek, a w WM_INITDIALOG ukrywasz te, które w danej konfiguracji nie są potrzebne.

0

I to dopiero działa.

Wywołanie w pętli głównej:

//  hTstBtn - uchwyt do przycisku  "test"
//  hWndExit - uchwyt do przycisku "exit"


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if((HWND)lParam == hWndExit && message == WM_COMMAND) { 
                                             DestroyWindow(hWnd); }
    if((HWND)lParam == hTstBtn && message == WM_COMMAND) { 
                                            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); }

 return 0;}

Pętla okna o nazw About:


// hEdit3 - uchwyt do okna edit
// Procedura obsługi komunikatów dla okna informacji o programie.

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        
        if (LOWORD(wParam) == IDOK) {
           
                HWND a1, a2,a3,a4,a5;
                 
                wchar_t hh[30];
                a3 = GetWindow(hDlg, GW_CHILD);
                a4 = GetWindow(a3, GW_HWNDNEXT);
                a5 = GetWindow(a4, GW_HWNDNEXT);
                a1 = GetWindow(a5, GW_HWNDNEXT);
                a2 = GetWindow(a1, GW_HWNDNEXT);
                GetWindowText(a2, (LPWSTR)hh, 20);
                SetWindowText(hEdit3, hh);
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;

        }
        
        if (LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Plik z źródłem WindowProject11.rc

//Skrypt zasobów wygenerowany przez program Microsoft Visual C++.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Wygenerowane z zasobu TEXTINCLUDE.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK)
LANGUAGE 21, 1

/////////////////////////////////////////////////////////////////////////////
//
// Ikona
//

// Ikona z najniższą wartością identyfikatora jest umieszczana jako pierwsza, aby zapewnić, że ikona aplikacji
// pozostają spójne we wszystkich systemach.

IDI_WINDOWSPROJECT11       ICON         "WindowsProject11.ico"
IDI_SMALL               ICON         "small.ico"

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDC_WINDOWSPROJECT11 MENU
BEGIN
    POPUP "&Plik"
    BEGIN
        MENUITEM "Za&kończ",                IDM_EXIT
    END
    POPUP "Pomo&c"
    BEGIN
        MENUITEM "&Informacje...",           IDM_ABOUT
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Akcelerator
//

IDC_WINDOWSPROJECT11 ACCELERATORS
BEGIN
    "?",            IDM_ABOUT,              ASCII,  ALT
    "/",            IDM_ABOUT,              ASCII,  ALT
END


/////////////////////////////////////////////////////////////////////////////
//
// Okno dialogowe
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Informacje WindowsProject11"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "WindowsProject11, Wersja 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (c) 2023",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
    EDITTEXT        IDD_EDITXT, 0, 0, 200, 200,

END

/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 163
        TOPMARGIN, 7
        BOTTOMMARGIN, 55
    END
END
#endif    // APSTUDIO_INVOKED

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////
//
// Tabela ciągów
//

STRINGTABLE
BEGIN
   IDC_WINDOWSPROJECT11   "WINDOWSPROJECT11"
   IDS_APP_TITLE       "WindowsProject11"
END

#endif
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Wygenerowane z zasobu TEXTINCLUDE.
//

/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
0

@Stefan_3N: już prawie wszystko mi ładnie działa, poza jedną rzeczą, w tym oknie edit co się pojawia do edycji, nie moge go ustawić od razu z kursorem. Poradzisz coś?

0

Nie wiem dokładnie co tam masz :-)

Jeśli kontrolka jest w dialogu, to wartość zwracana z WM_INITDIALOG decyduje o tym czy system ma ustawić focus.
Kontrolka, na której zostanie ustawiony focus - to pierwsza kontrolka w dialogu, która może focus przyjąć.
Ponadto mamy komunikat WM_NEXTDLGCTL, za pomocą którego przestawiamy focus na inną kontrolkę (wyślij ten komunikat za pomocą PostMessage). Kontrolka, która może mieć w ten sposób ustawiony focus musi mieć styl WS_TABSTOP.

Ale być może masz tę kontrolką poza dialogiem.
Wtedy spróbuj po jej wyświetleniu wykonać na niej SetFocus(hEdit).

Zauważyłem też, że użyłeś stylu WS_GROUP. Przyjrzyj się dokładnie w dokumentacji, co ten styl robi (ma wpływ na to jak system obsługuje "chodzenie": po kontrolkach za pomocą klawiatury).

0

Probowałem użyć SwitchToThisWindow(), starałem się przełączyć to na kontrolkę edit w oknie About i chyba nie zrobiłem tego przy wyłączaniu okna About() z powrotem na okno główne, teraz mi wisi program w systemie i nie się go zamknąć. Ani process explorerem ani niczym innym. Zaraz spróbuje tego postmessage.

Jest faktycznie usunąłem ok buttona i edit od razu pojawił się z kursorem thx.

Teraz mam edytowalnego list boxa, a zaraz zrobię ich kilka, zrobię jakąś większą bazę danych na listach łączonych (wraz z zapisem do pliku i odczytem) i wszystko zmienie w edytowalnego datagrid.

xD

0

Czemu nie użyjesz po prostu ListView?
W ListView, ta kontrolka edycyjna, z która walczysz jest wbudowana.
Pokazałem Ci jak obsługiwać TreeView, ListView obsługujemy analogicznie, tylko że z innymi strukturami.

0

"Pokazałem Ci jak obsługiwać TreeView" -- " fatal error C1014: zawiera zbyt wiele plików dołączanych: głębokość = 1024"

", ta kontrolka edycyjna, z która walczysz " - this what I do xD

0

Jest sprawa, to ListView chyba nie pozwala mi skakać po polach bocznych kursorem. Po jednej kolumnie tak ale w boki chyba nie.

0

Nie wiem, czy Dev-C++ ma zdefiniowane wszystko co trzeba, ale zawsze możesz sobie to zdefiniować.

ListView w trybie LVS_REPORT pozwala edytować tylko pierwsza kolumnę.
Ale masz komunikat LVM_GETEDITCONTROL, który zwróci Ci uchwyt do kontrolki edycyjnej.
Aby rozpocząć edycję wyślij LVM_EDITLABEL.
Kontrolka wyśle do Ciebie LVN_BEGINLABELEDIT. Wtedy ustaw pozycję i wpisz tekst do edycji. Odpowiedz FALSE, żeby kontynuować edycję.
Po kliknięciu Entera kontrolka wyśle LVN_ENDLABELEDIT. Wtedy odczytaj zawartość i odpowiedz TRUE lub FALSE (w zależności co tam chcesz z tym zrobić).
Zrób to w WM_NOTIFY, jak pokazałem w przykładzie wyżej dla TreeView.

0

LVS_REPORT - a są inne tryby?
Edycje kontrolki już mam ale tylko pierwszej kolumny. A ja chcę chodzić po bocznych polach i je edytować. Tak jak to jest w DataGrid.

0

https://learn.microsoft.com/en-us/windows/win32/controls/list-view-window-styles

Napisałem wyżej jak przechwycić kontrolkę edycyjną.
Mając do niej uchwyt możesz ją przesunąć gdzie chcesz. Współrzędne poszczególnych kolumn odczytasz za pomocą LVM_GETITEMRECT.
Myślę, że w sieci znajdziesz sporo przykładów, jak to zrobić.

0

Wyszło nawet bardziej zajebiście niż myślałem. W odpowiedzi na dwuklik w listboxie okienko edit w tym okienku pojawiającym się powiększa się delikatnie ponad
no full wypas he he
Kusi mnie, żeby pod enterem na listboxie dodac edycje, ale sam nie wiem, bo mogłoby wyświetlać jakieś podsumowanie w nowym oknie (funkcje by się przydały do ustawiania parametrów okna - tego About).
Chyba się zajmę programowaniem xD
111111a.jpg

0

@Stefan_3N a wiesz może jak zatrzymać przesunięcie kursora klawisza? Tak jak napisałeś, jak mam w ListBox kursor i chcę przenieść focus na innego ListBoxa to robię SetFocus(AnotherListBox) ALE kursor mi przenosi w dół.

0

Chyba zabierasz się za to od złej strony :-)
Nie widzę kodu, ale chyba masz to nie w oknie dialogowym tylko w zwykłym oknie?

Jak pisałem - w oknie dialogowym przesuwasz focus na inną kontrolkę za pomocą WM_NEXTDLGCTL.
Nie wiem, czy ten komunikat zadziała w zwykłym oknie.

Jeśli masz okno główne (zwykłe) i w nim chcesz mieć kontrolki, to utwórz niemodalne okno dialogowe (bez belki tytułowej ze stylem WS_CHILD). Takie okno tworzysz za pomocą CreateDialog() (w niektórych plikach pomocy jest błąd i jest podane, że ta funkcja niczego nie zwraca, ale ona zwraca uchwyt do utworzonego okna).
I na tej "podkładce" rozmieść swoje kontrolki.
W głównej pętli komunikatów (okna głównego) dodajesz IsDialogMessage().
Wtedy będziesz miał dostęp do szeregu funkcji działających w dialogu.

Standardowo w systemie Windows focus jest przenoszony na kolejne kontrolki za pomocą klawisza Tab (do przodu) lub Shift + Tab (do tyłu). I jeśli zrobisz to w oknie dialogowym, to obsługa Tab działa z automatu.

Jeśli mimo wszystko chcesz to zrobić w zwykłym oknie i na dodatek chcesz, żeby klawisz kursora przenosił użytkownika do innej kontrolki (tak zrozumiałem Twoje pytanie), to subklasuj ListBoxa i przechwyć mu WM_KEYDOWN.

0

@Stefan_3N: Rozumiem nie kojarzysz takiej funkcji "ProcessCmdKey()" ?

A z tym co mogę zrobić?

Bo wygląda obiecująco

 MSG msg;

    // Główna pętla komunikatów:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
0

Ta funkcja chyba nie jest z WINAPI (chyba, ze czegoś nie wiem).

1 użytkowników online, w tym zalogowanych: 0, gości: 1