WS_POPUP et focus

vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 - 1 mai 2006 à 16:09
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 - 4 mai 2006 à 12:45
C'est un problème assez compliqué a expliquer...
J'ai remarqué que les menus (obtenus par exemple avec TrackPopupMenu) sont des fenêtre popup (avec le style WS_POPUP).
Ce que je ne comprends pas, c'est que malgré tout la fenêtre parente garde le focus alors qu'une fenêtre popup a été créée (la Title Bar reste bleue);
J'essaie de faire la même chose (mais sans TrackPopupMenu car ce n'est pas un menu que je fais), mais dès que je crée une fenêtre popup, la fenêtre principale perd le focus (sa barre de titre devient grise).
Je cherche donc le moyen de faire comme TrackPopupMenu
Si quelqu'un a déja fait ca, merci de m'aider

25 réponses

nightlord666 Messages postés 746 Date d'inscription vendredi 17 juin 2005 Statut Membre Dernière intervention 23 mai 2007 10
1 mai 2006 à 18:12
Tu a essayé de faire un SetFocus après la création de ta fenêtre WS_POPUP ?
0
yoyo269 Messages postés 1403 Date d'inscription lundi 23 février 2004 Statut Membre Dernière intervention 11 janvier 2009 2
1 mai 2006 à 18:15
SetFocus ne te suffirait pas ?

YOYO, @+.
"L'intelligence c'est comme un parachute, quand on en n'a pas...on s'écrase !"
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 mai 2006 à 18:56
Ben dès que je clique a nouveau sur la fenêtre popup, elle perd à nouveau le focus...
Ce que je veux faire, c'est comme dans Office, le menu qui apparait dans la commande Undo/Redo de la barre d'outils
0
nightlord666 Messages postés 746 Date d'inscription vendredi 17 juin 2005 Statut Membre Dernière intervention 23 mai 2007 10
1 mai 2006 à 18:58
Tu a essayé de faire une fenêtre avec le style WS_EX_TOOLWINDOW ? (c'est un style extended, donc à utiliser avec CreateWindowEx)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 mai 2006 à 19:01
Oui j'ai essayé ca, et pas mal d'autres trucs.
Le seul truc que j'ai c'est de donner le focus a la fenêtre parente et d'enpêcher la popup de devenir active (je retourne MA_NOACTIVATE quand je recois WM_ACTIVATE). Par contre ca pose d'autres problèmes que j'ai du mal à régler
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
1 mai 2006 à 19:10
Le code interne de TrackPopupMenu est assez compliqué (je viens d'aller voir).
La fenêtre mère est illico sous classée, pointeur sur le menu lui est refilé, remise de la bonne proc quand suppression du menu.
C'est un énorme souk alors pas le temps d'en faire le détail.

ciao...
BruNews, MVP VC++
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 mai 2006 à 19:16
D'après ce que j'ai compris, c'est la fenêtre parente qui a la capture de la souris. Tu peux me confirmer cela?
0
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
1 mai 2006 à 19:25
Salut,
vecchio56 >> Tu ne veux pas utiliser une petite boite de dialogue créée avec CreateDialog()? La fenêtre mère peut garder le focus et la boite reste toujours visible.
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
1 mai 2006 à 19:39
CreateDialog semble une bonne piste.

vecchio > semble bien mais vraiment pas le temps de lire tous les fichiers sources. Note tout ce que tu voudrais consulter et on fera cela une autre fois.

ciao...
BruNews, MVP VC++
0
cs_Joky Messages postés 1787 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 31 janvier 2009 2
1 mai 2006 à 21:05
Moi j'trouve ça étonnant que BruNews ait accès aux codes sources de toutes ces fonctions lol.

if(!Meilleur("Joky")) return ERREUR;<
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 mai 2006 à 22:52
J'ai pas l'habitude d'utiliser CreateDialog(), mais quelle différence avec un CreateWindow exactement?
Le problème, c'est que:
-la fenêtre mère doit garder le focus, et même capturer la souris
-l'autre fenêtre contient éventuellement des controles (une scrollbar) que je dois pouvoir utiliser
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
1 mai 2006 à 23:10
Gestion simplifiée des events comme (presque) DialogBoxParam mais non modale.

ciao...
BruNews, MVP VC++
0
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
2 mai 2006 à 04:42
La je pense avoir compris ce que tu veux faire exactement. Une boite de dialogue créée avec CreateDialog() ne conviendra pas quand celle-ci doit contenir des controles pouvant avoir besoin du focus comme un Edit ou une ScrollBar. Car cela fait perdre le focus à la fenêtre principale.
La solution est de créer une fenêtre fille. Celle-ci contiendra l'Edit ou la ScrollBar. La fenêtre principale ne perdra pas le focus suite au clic sur l'un des deux controles. J'ai déjà utilisé cette méthode sans problème.
Voici un petit exemple complet:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int creation=0;
static HWND fille,bar,edit;

switch (msg)
{
case WM_CREATE:
if (!creation)
{
creation=1;
fille = CreateWindowEx(0,"classe",0,WS_DLGFRAME | WS_CHILD | WS_VISIBLE, 20,20,160,100,hWnd,0,0,0);
bar=CreateWindowEx(0,"SCROLLBAR",0,WS_CHILD | WS_VISIBLE | SBS_HORZ, 20,20,110,20,fille,0,0,0);
edit=CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT" ,0, WS_CHILD | WS_VISIBLE, 20,50,110,20,fille,0,0,0);
}
return 0;

case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
return 0;
}




int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszMenuName = 0;
wc.lpszClassName = "classe";
wc.hIconSm = 0;
RegisterClassEx(&wc);

HWND hwnd = CreateWindow("classe", 0, WS_SYSMENU | WS_MINIMIZEBOX ,0,0, 400, 300, 0, 0, hInstance,0);
if (!hwnd) return FALSE;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}

Dans cet exemple, la fenêtre principale et la fenêtre fille sont de la même classe. Elles partagent donc la même procédure WNDPROC. Cela permet de traiter les messages (générés par l'utilisation des controles de la fenêtre fille) dans une seule procédure.
La variable "création" permet de ne créer la fenêtre fille et ses controles que pendant la création de la fenêtre principale.
Dans ton programme, tu pourras cacher ou montrer la fenêtre fille quand tu veux.
Voilà, j'espère que cette solution te conviendra.
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
2 mai 2006 à 11:39
Merci de ton aide
J'avais bien pensé à la fenêtre fille, mais je ne comprends pas pourquoi, je n'arrive pas à l'amener au permier plan (j'ai déja plein de fenêtres filles partout).
Pourtant j'ai mis celle ci en WS_EX_TOPMOST, et j'ai fait un SetWindowPos avec HWND_TOP, mais elle disparait tout de suite derrière les autres
0
yoyo269 Messages postés 1403 Date d'inscription lundi 23 février 2004 Statut Membre Dernière intervention 11 janvier 2009 2
2 mai 2006 à 13:05
Et avec SetForegroundWindow ?

YOYO, @+.
"L'intelligence c'est comme un parachute, quand on en n'a pas...on s'écrase !"
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
2 mai 2006 à 13:41
J'ai déja essayé mais non, ca ne marche pas
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
2 mai 2006 à 13:56
Voici un exemple de code qui illustre le problème.
On appuie sur une touche pour créer la nouvelle fenêtre
-Si la fenêtre est popup, la fenêtre mère perd le focus, ce que je ne veux pas
-Si la fenêtre est fille, ca ne marche pas bien du tout

#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501
#include <windows.h>

HINSTANCE g_hInst;
HWND g_hWnd;

LRESULT CALLBACK AppWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND h;
switch(uMsg)
{
case WM_CREATE:
CreateWindowA("BUTTON", "Bouton", WS_VISIBLE | WS_CHILD, 0, 0, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_VISIBLE | WS_CHILD, 0, 200, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_VISIBLE | WS_CHILD, 200, 0, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("BUTTON", "Bouton", WS_VISIBLE | WS_CHILD, 200, 200, 200, 200, hWnd, 0, g_hInst, 0);
break;
case WM_KEYDOWN:
//h = CreateWindowEx(0, "Classe2", "Classe2", WS_BORDER | WS_VISIBLE | WS_CHILD, 10, 10, 200, 200, hWnd, 0, g_hInst, 0);
h = CreateWindowEx(0, "Classe2", "Classe2", WS_BORDER | WS_VISIBLE | WS_POPUP, 10, 10, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_VISIBLE | WS_CHILD, 0, 0, 200, 200, h, 0, g_hInst, 0);
SetForegroundWindow(h);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
MSG msg;
g_hInst = GetModuleHandle(0);
WNDCLASSEX wcex;

memset(&wcex, 0, sizeof wcex);
wcex.cbSize = sizeof wcex;
wcex.lpfnWndProc = AppWndProc;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = g_hInst;
wcex.lpszClassName = "Classe1";
wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
if(!RegisterClassEx(&wcex)) return 1;

wcex.cbSize = sizeof wcex;
wcex.lpfnWndProc = DefWindowProc;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = g_hInst;
wcex.lpszClassName = "Classe2";
wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
if(!RegisterClassEx(&wcex)) return 1;

g_hWnd = CreateWindowEx(0, "Classe1", "Classe1", WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, 0, 0, g_hInst, 0);
if(!g_hWnd) return 1;

ShowWindow(g_hWnd, SW_NORMAL);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
2 mai 2006 à 15:05
Cette fois j'y suis presque. Le seul problème est que l'edit ne recoit pas les événements du clavier (car il n'a pas le focus, et on ne peut pas le lui donner)
L'astuce était de faire SetParent(hPopup, HWND_DESKTOP);

#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501
#include <windows.h>

HINSTANCE g_hInst;
HWND g_hWnd, hPopup = 0;

LRESULT CALLBACK AppWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
CreateWindowA("BUTTON", "Bouton", WS_VISIBLE | WS_CHILD, 0, 0, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_VISIBLE | WS_CHILD, 0, 200, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_VISIBLE | WS_CHILD, 200, 0, 200, 200, hWnd, 0, g_hInst, 0);
CreateWindowA("BUTTON", "Bouton", WS_VISIBLE | WS_CHILD, 200, 200, 200, 200, hWnd, 0, g_hInst, 0);
break;
case WM_KEYDOWN:
if(!hPopup)
{
// WS_EX_TOOLWINDOW permet de na pas voir la fenêtre dans la barre des taches
hPopup = CreateWindowEx(WS_EX_TOOLWINDOW, "Classe2", "Classe2", WS_BORDER | WS_VISIBLE | WS_CHILD, 10, 10, 202, 202, hWnd, 0, g_hInst, 0);
CreateWindowA("EDIT", 0, WS_CLIPSIBLINGS | WS_VSCROLL | WS_VISIBLE | WS_CHILD, 0, 0, 200, 200, hPopup, 0, g_hInst, 0);
SetParent(hPopup, HWND_DESKTOP);
//SetActiveWindow(hPopup);
//SetFocus(h);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
MSG msg;
g_hInst = GetModuleHandle(0);
WNDCLASSEX wcex;

memset(&wcex, 0, sizeof wcex);
wcex.cbSize = sizeof wcex;
wcex.lpfnWndProc = AppWndProc;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = g_hInst;
wcex.lpszClassName = "Classe1";
wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
if(!RegisterClassEx(&wcex)) return 1;

wcex.cbSize = sizeof wcex;
wcex.lpfnWndProc = DefWindowProc;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = g_hInst;
wcex.lpszClassName = "Classe2";
wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
if(!RegisterClassEx(&wcex)) return 1;

g_hWnd = CreateWindowEx(0, "Classe1", "Classe1", WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, 0, 0, g_hInst, 0);
if(!g_hWnd) return 1;

ShowWindow(g_hWnd, SW_NORMAL);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
0
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
3 mai 2006 à 16:56
Salut,
Dans le cas de plusieurs fenêtres filles, c'est vrai que le problème d'activation des fenêtres se pose. Il parait que SetWindowsPos() et SetForegroundWindow() ne fonctionnent que pour le bureau comme fenêtre mère. Il faudra penser à des solutions plus compliquées permettant le redessin et l'activation des fenêtres filles.
Ton astuce est intéressante mais semble insuffisante.
J'aurai certainement un jour besoin d'un truc pareil. Je m'y pencherai quand j'aurai du temps si personne ne trouve de solution avant.
Bonne chance.
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
3 mai 2006 à 16:59
J'ai totalement réussi a faire ce que je voulais au début, mais c'est vrai qu'a certains endroits ils faut bidouiller, et j'y suis arrivé car c'était finalement assez simple
0
Rejoignez-nous