Dialog tworzony podczas działania programu

0

Witam. utworzyłem dialog wedlug poradnika http://cpp0x.pl/kursy/Kurs-WinAPI-C++/Podstawy/Okna-dialogowe-cz-7/190.

gdy tworze dialog modalny funkcją:

DialogBoxIndirect( hThisInstance,( DLGTEMPLATE * ) hgbl, hwnd,( DLGPROC ) DialogProc );

widze swój dialog, jednak ja potrzebuje niemodalnego dialogu. Z poprzednich kursów CreateDialog() wywoływało dialog niemodalny, więc spróbowałem funkcji z powyższego kursu:

CreateDialogIndirect( hThisInstance,( DLGTEMPLATE * ) hgbl, hwnd,( DLGPROC ) DialogProc );

Niestety teraz nie widzę żadnego dialogu jakbym w ogóle go nie wyświetlał. Macie jakies pomysły?

Tutaj tworze okno dialogu i go wyświetlam:

 
{ /// okno pulpitu
                WINDOWINFO Info;
                Info.cbSize = sizeof(WINDOWINFO);
                GetWindowInfo(GetDesktopWindow(), &Info);
                int x = Info.rcClient.right   -150 -0;
                int y = Info.rcClient.bottom  -23  -30;

                hgbl = GlobalAlloc( GMEM_ZEROINIT, 1024 );
                pdt =( DLGTEMPLATE * ) GlobalLock( hgbl );

                pdt->style = WS_POPUP;
                pdt->cdit = 1;

                RECT rcDlg = { x, y, 150, 23 };
                PixelsToDialogUnits( rcDlg );

                pdt->x =( short ) rcDlg.left;
                pdt->y =( short ) rcDlg.top;
                pdt->cx =( short ) rcDlg.right;
                pdt->cy =( short ) rcDlg.bottom;

                pw =( WORD * )( pdt + 1 );
                * pw++ = 0x0; // brak menu
                * pw++ = 0x0; // predefiniowana klasa dialogu

                pws =( LPWSTR ) pw;
                nchar = 1 + MultiByteToWideChar( CP_ACP, 0, "Dodaj wpis...", - 1, pws, 50 );
                pw += nchar;

                pw = lpwAlign( pw );
                pdit =( DLGITEMTEMPLATE * ) pw;
/// EDIT
                pw = lpwAlign( pw );
                pdit =( DLGITEMTEMPLATE * ) pw;

                RECT rcEdit = { 25, 10, 150, 25 };
                PixelsToDialogUnits( rcEdit );

                pdit->x =( short ) rcEdit.left;
                pdit->y =( short ) rcEdit.top;
                pdit->cx =( short ) rcEdit.right;
                pdit->cy =( short ) rcEdit.bottom;

                pdit->id = 1000;
                pdit->style = WS_CHILD | WS_VISIBLE | WS_BORDER;

                pw =( WORD * )( pdit + 1 );
                * pw++ = 0xffff;
                * pw++ = 0x0081; // edit box

                pws =( LPWSTR ) pw;
                nchar = 1 + MultiByteToWideChar( CP_ACP, 0, "Tekst", - 1, pws, 50 );
                pw += nchar;
                * pw++ = 0; // brak dodatkowych danych



 }

a po wyświetleniu głównego okna próbuje wywołac dialog:

 
        ShowWindow (hwnd, nCmdShow);

        GlobalUnlock( hgbl );
        CreateDialogIndirect( hThisInstance,( DLGTEMPLATE * ) hgbl, hwnd,( DLGPROC ) DialogProc );
        GlobalFree( hgbl );
0

Spróbuj użyć DialogBoxParam()

0

Strzelasz czy wiesz?

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645465%28v=vs.85%29.aspx

Bo tu pisze, że to tworzy dialog modalny w dalszym ciągu z ta róznicą, że mozna podac argument lParam który można wykorzystac w WM_INITDIALOG.

usunięcie znacznika <code class="cpp"> - @furious programming

0

Przecież jest dialog tylko pokręciłeś z jego rozmiarami i pozycją na ekranie to tego styl tylko WS_POPUP (takie okno nie ma ramki, menu ani paska tytułu) a za chwilę ustawiasz tytuł to chyba nie było zamierzone...

0
  1. Tak, tytuł moge usunąć bo chodzi mi o sam edit bez niczego ;)
  2. Jeśli chodzi o dialog modalny wyswietla mi się w prawidłowej pozycji, natomiast jest problem z pojawieniem sie na ekranie dialogu niemodalnego.

I nasuwam kolejne pytanie:
jak uzyskać wskaźniki do kontrolek w tymże dialogu? po identyfikatorach da się? Bo nie chce nic namieszać ;c

0

Aby zrobić niemodalny to możesz użyć funkcji CreateDialogIndirect tylko aby był widoczny styl zrób WS_POPUP | WS_VISIBLE
Uchwyty kontrolek uzyskasz za pomocą funkcji GetDlgItem (jako drugi parametr podajesz ID kontrolki które podałeś w templatce).

0

Wszystkie poprzednie problemu są rozwiązane. Dziekuje wszystkim, którzy pomogli.

nastepny kłopot:
Przekierowuje komunikaty z kontrolki Edit znajdującej się w dialogu do procedury:

 
g_OldWndProc2 =( WNDPROC ) SetWindowLong( GetDlgItem(hwnd, ID_PULPITEDIT), GWL_WNDPROC,( LONG ) ListWndProc2 );
 
LRESULT CALLBACK ListWndProc2( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam )
{
    switch( mesg )
    {
        case WM_KEYDOWN:
        {
            MessageBox(0, "enter", "", MB_OK);
            switch(LOWORD(wParam))
            {
                case VK_RETURN:{
                    MessageBox(0, "", "", MB_OK);
                    int dlugosc = GetWindowTextLength(GetDlgItem(hwnd, ID_PULPITEDIT));
                    if(dlugosc == 0)
                    {
                        SendMessage(hLista, LB_SETCURSEL, -1, 0);
                        break;
                    }
                    char *tekst = new char[dlugosc+1];
                    GetWindowText(GetDlgItem(hwnd, ID_PULPITEDIT), tekst, dlugosc+1);
                    f_DodajNumer(tekst);
                    delete tekst;
                    break;
                }
            }
        }
        break;
    }
    return CallWindowProc( g_OldWndProc2, hwnd, mesg, wParam, lParam );
}

W identyczny sposób przekierowuję komunikaty z kontrolki edit znajdującej się w głównym oknie. Problem polega na tym, że wykrywanie nacisniecia przycisku "ENTER" w polu tekstowym w dialogu mi nie działa (a w głównym oknie owszem). Natomiast działa np. wcisnięcie "CTRL" (wyświetla się MessageBox() po WM_KEYDOWN).

Podejrzewam, że może byc to spowodowane obsługą Tabu przez dialog, ale nie jestem pewien i nie wiem jak go wylączyć, bo w sumie nie jest mi ani troche potrzebny.

1

Niemożliwe coś ścieniasz jeżeli dialog nie jest modalny (czyli np. utworzony funkcją CreateDialogIndirect) to musi działać chyba ze coś poknociłeś w kodzie:

LRESULT CALLBACK EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_KEYDOWN: {
						 switch (LOWORD(wParam))
						 {
						 case VK_RETURN:
							 OutputDebugString(L"ENTER\n"); //To się wykonuje!
							 break;
						 }
	}
	}
	return CallWindowProc(g_OldEditProc, hwnd, msg, wParam, lParam);
}

BOOL CALLBACK DialogProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch (Msg)
	{
	case WM_INITDIALOG:
	  g_OldEditProc = (WNDPROC)SetWindowLong(GetDlgItem(hwnd, ID_PULPITEDIT), GWL_WNDPROC, (LONG)EditWndProc);
	  return true;
        //ciach
0

@kAzek przez nieuwage pozostawiłem modalny dialog. Zmieniłem na niemodlany, dodałem flage WS_VISIBLE i smiga wszystko. Również ENTER teraz chodzi ! Dziekuje i miłego dnia. temat zamkniety.

Ehhh jeszcze jedno:

Jak mam utworzony dialog i w nim sam "Edit" jak zrobić, żeby po ShowWindow(hDialog); mozna było od razu wpisywac tekst bez klikania wpierw na edita?
Próbowałem SetFocus(hEdit); ale dzieki temu mryga kursor w edicie. Wpisywać moge dopiero po kliknięciu na niego.

Edit1:
Wychodzi na to, że chyba Edit jest aktywowany, a Dialog nie. próbowałem SW_RESTORE bo ta flaga według dokumentacji ma też aktywować okno, niestety nie dziala jak należy.

0

Wywołaj SetActiveWindow(hDialog); a w procedurze Dialogu:

	case WM_ACTIVATE:
		if (wParam > 0) {
			SetFocus(hEdit);
		}
	    break;
0

Ewentualnie przetłumacz sobie to na C++ albo używaj konstrukcji z deklaracji tej procedury:

procedure SetDialogFocus(DialogHandle, ControlHandle : HWND);
begin
  SendMessage(DialogHandle, WM_NEXTDLGCTL, ControlHandle, 1);
end;
0

Niestety bez efektu dalej to samo.

Edit1:
Dodam pare szczegółów:

  • Dialog jest jednak niemodalny (i początkowo niewidoczny)
  • Główne okno jest niewidoczne (SW_HIDE)
  • Klikam LPM na tray'a i dialog się ukazuje
case CMSG_TRAY:{
            if( wParam == ID_TRAY )
            {
                if( lParam == WM_LBUTTONDOWN ){
                    if(!aktywny){
                        aktywny = true;
                        ShowWindow(hDialog, SW_SHOW);
                        SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), "");
                        SetActiveWindow(hDialog);                                         //probowalem
                        SendMessage(hDialog, WM_NEXTDLGCTL, ID_PULPITEDIT, 1);           //probowalem
                    }
                    else
                    {
                        aktywny = false;
                        ShowWindow(hDialog, SW_HIDE);
                    }
                }
                if( lParam == WM_LBUTTONDBLCLK ){
                    SendMessage(hwnd, WM_SIZE, SIZE_MAXIMIZED, 0);
                    aktywny = false;
                    ShowWindow(hDialog, SW_HIDE);
                    SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), "");
                }
            }
  • jednak nie moge nic w niego wpisać póki nie klikne na dialogu myszką aktywując go (kursor w edicie mryga)
  • Próbowałem tych sposobów, które przeczytałem od Was.

poprawienie wypunktowania - @furious programming

0

Dziwna sprawa, sprawdziłem u siebie i jeżeli okno jest niewidoczne to samo wywołanie ShowWindow powinno go pokazać i aktywować (u mnie tak się dzieje) obsługa WM_ACTIVATE jest niekonieczna jeżeli Edit jest jedyną kontrolką w Dialogu to i tak będzie aktywny ale można zostawić na wszelki wypadek. Jak nie działa to chyba musiałeś przekombinować albo coś deaktywuje Ci dialog... Zrób sobie test w procedurze obsługi dialogu:

	case WM_ACTIVATE:
		if (wParam > 0) {
			SetFocus(hEdit);
			OutputDebugString(L"aktywny\n");
		}
		else {
			OutputDebugString(L"nieaktywny\n");
		}
	    break; 

Przed uruchomieniem w IDE ustaw aktywną zakładkę na Output i po kliknięciu ikony w trayu powinno wypisać "aktywny"
PS: Ta zmienna aktywny Ci chyba niepotrzebna:

	case CMSG_TRAY:{
					   if (wParam == ID_TRAY){
						   if (lParam == WM_LBUTTONDOWN){
							   SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), L"");
							   ShowWindow(hDialog, !IsWindowVisible(hDialog));
						   }
					   }
	    }
		break;
0

Nie wiem, czy wczesniej prawidłowo wytłumaczylem Wam problem. Mam go też przy przywracaniu głównego okna klikając podwójnie LPM na tray'a.

Podam przykład:

  1. Minimalizuję główne okno (pojawia się Tray)
  2. uruchamiam sobie stos innych programów i pracuje na nich...
  3. Zachciało mi się znów przywrócić moje okno więc klikam podwójnie LPM na tray'a
  4. Główne okno pojawia się (jak sobie życzyłem) z tą róznicą, że jest pod tymi wszystkimi przeglądarkami, wordami itp., a aktywnym oknem jest dalej ostatnio używany program. Zależy mi na tym, aby wląsnie po kliknięciu traya okno weszło ponad wszystkie i przyjmowało komunikaty ;)
0

Tak jak wcześniej pisałem takie zachowanie nie jest normalne i musiałeś coś przekombinować w programie (może coś z obsługą komunikatów np. nie wykonuje się DefWindowProc tam gdzie powinien) ... no ale bez kodu nie da się zgadnąć co zrobiłeś :/

0

Tutaj zamieszczam całą procedurę podpietą pod główne okno:

 
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case CMSG_TRAY:{
            if( wParam == ID_TRAY )
            {
                if( lParam == WM_LBUTTONDOWN ){
                        ShowWindow(hDialog, !IsWindowVisible(hDialog));
                        SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), "");
                }
                if( lParam == WM_LBUTTONDBLCLK ){
                    SendMessage(hwnd, WM_SIZE, SIZE_MAXIMIZED, 0);
                    ShowWindow(hDialog, SW_HIDE);
                    SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), "");
                }
            }

            break;
        }
        case WM_SIZE:{
            if( wParam == SIZE_MINIMIZED ){
                ShowWindow( hwnd, SW_HIDE );
                status.nid.cbSize = sizeof( NOTIFYICONDATA );
                status.nid.hWnd = hwnd;
                status.nid.uID = ID_TRAY;
                status.nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                status.nid.uCallbackMessage = CMSG_TRAY;
                status.nid.hIcon = LoadIcon( NULL, IDI_APPLICATION );
                lstrcpy( status.nid.szTip, status.nazwa );
                Shell_NotifyIcon( NIM_ADD, & status.nid );
            }
            if( wParam == SIZE_MAXIMIZED ){
                ShowWindow( hwnd, SW_RESTORE );
                status.nid.cbSize = sizeof( NOTIFYICONDATA );
                status.nid.hWnd = hwnd;
                status.nid.uID = ID_TRAY;
                status.nid.uFlags = 0;
                Shell_NotifyIcon( NIM_DELETE, & status.nid );
                // 2
            }
            break;
        }
        case WM_COMMAND:{
            switch(wParam)
            {
                case ID_DODAJ:{
                    char *tekst = new char[50];
                    int dlugosc = GetWindowTextLength(hWpisz);
                    GetWindowText(hWpisz, tekst, dlugosc+1);
                    f_DodajNumer(tekst);
                    delete tekst;
                    break;
                }
                case ID_USUN:{
                    f_UsunNumer();
                    break;
                }
            }
            break;
        }
        case WM_TIMER:{
            f_AdresWyswietl(SendMessage(hAdresLista, LB_GETCURSEL, 0, 0));

            int index = SendMessage(hLista, LB_GETCURSEL, 0, 0);
            if(index != -1)
            {
                string tekst = "Data wystawienia: ";
                tekst += vCzas[index];
                SetWindowText(hInformacje, tekst.c_str());
                tekst.clear();
            }
            else
                SetWindowText(hInformacje, "");
            int dlugosc = GetWindowTextLength(hWpisz);
            if(dlugosc == 0){
                break;
            }
            char *tekst = new char[dlugosc+1];
            GetWindowText(hWpisz, tekst, dlugosc+1);
            f_WyszukajFraze(tekst);

            delete tekst;
            break;
        }
        case WM_CLOSE:{
            for(int n=0; n<(int)vCzas.size(); n++)
                UsunStrukture(0);
        }
        case WM_DESTROY:{
            KillTimer(hwnd, 1);

            if( IsIconic( hwnd ) )
            {
                NOTIFYICONDATA nid;
                nid.cbSize = sizeof( NOTIFYICONDATA );
                nid.hWnd = hwnd;
                nid.uID = ID_TRAY;
                nid.uFlags = 0;
                Shell_NotifyIcon( NIM_DELETE, & nid );
            }

            PostQuitMessage (0);
            break;
        }
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}

Tutaj po kliknięciu podwójnie na Tray'a wywołuje komunikat

 
if( lParam == WM_LBUTTONDBLCLK ){
     SendMessage(hwnd, WM_SIZE, SIZE_MAXIMIZED, 0);
     ShowWindow(hDialog, SW_HIDE);
     SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), "");
}

który obsługuje tu: (po tym okno według dokumentacji SW_RESTORE powinno sie od razu aktywować)

 
if( wParam == SIZE_MAXIMIZED ){
                ShowWindow( hwnd, SW_RESTORE );

Oczywiście ten problem, który teraz opisuję nie przeszkadza mi zbytnio. Chcę po prostu wiedzieć na przyszłość co jest nie tak :)
I jeszcze raz dziekuje wszystkim za pomoc w poprzednich problemach.

0

Ja to chyba zostanę jasnowidzem z tego co widzę tak jak przypuszczałem cały problem sprowadza się do braku wywołania DefWindowProc. Nie mam czasu teraz się bawić i doprowadzać do używalności obsługi WM_SIZE ale mam działającą z mojego kodu na którym testowałem obsługę tego za pomocą WM_SYSCOMMAND"

	case WM_SYSCOMMAND: {
		NOTIFYICONDATA nid;
		nid.cbSize = sizeof(NOTIFYICONDATA);
		nid.hWnd = hWnd;
		nid.uID = ID_TRAY;
		if (wParam == SC_MINIMIZE) {
			LPWSTR sTip = L"Test App";
			nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
			nid.uCallbackMessage = CMSG_TRAY;
			nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
			lstrcpy(nid.szTip, sTip);
			Shell_NotifyIcon(NIM_ADD, &nid);
			ShowWindow(hWnd, SW_HIDE);
			return 0; //tu nie wywolujemy DefWindowProc bo okno schowane wiec system nic madrego z nim nie zrobi
		}
		else if (wParam == SC_RESTORE) {
			nid.uFlags = 0;
			Shell_NotifyIcon(NIM_DELETE, &nid);
		}}	
		return DefWindowProc(hWnd, message, wParam, lParam); //ale w kazdym innym przypadku trzeba wywolac domyslna obsluge tego komunikatu 
	case CMSG_TRAY:
		if (wParam == ID_TRAY){
			if (lParam == WM_LBUTTONDOWN){
				SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), L"");
				ShowWindow(hDialog, !IsWindowVisible(hDialog));
			}
			else if (lParam == WM_LBUTTONDBLCLK){
				ShowWindow(hDialog, SW_HIDE);
				ShowWindow(hWnd, SW_SHOW);
				SetWindowText(GetDlgItem(hDialog, ID_PULPITEDIT), L"");
			}
		}
		break;

W Dialogu jak dalej nie działa jak trzeba też pewnie masz jakieś podobne babole.

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