Récupérer un CallBack [Résolu]

Signaler
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009
-
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009
-
Bonjour tlm,

J'a créé une classe qui permet de mettre une icone dans le systray (avec des API et pas le framework). Mais un problème se pose. J'ai envie d'être averti au moment ou l'utilisateur clique sur l'icone dans le systray. Mais comment faire?

J'ai utilisé la fonction PeekMessage mais elle me ressort pas le moment ou l'utilisateur clique sur l'icone

Dans le struct (NOTIFYICON)
SystrayStr.uCallBackMessage WM_RBUTTONDOWN;

Et ensuite j'ai un thread qui reprend les événement
struct POINTAPI
{
public int x;
public int y;
}
struct MSG
{
public int hwmd;
public int message;
public int wParam;
public int lParam;
public int time;
public POINTAPI pt;
}

[ DllImport( "user32.dll", SetLastError = true ) ]
private static extern bool PeekMessage(ref MSG lpMsg,int hwnd,Int32 wMsgFilterMin,Int32 wMsgFilterMax, PeekMessageOption wRemoveMsg);

private void ecoute()
{
MSG message = new MSG();
while(true)
{
if(PeekMessage( ref message, 0, 0, 0, 0))
{
if(message.wParam ==(int)NotifyCallback.WM_LBUTTONDBLCLK) // double clic
{
//L'utilisateur a cliqué
}
}
}
}

Je n'arrive pas a récupérer le message normalement renvoyé (CallBack?). message.wParam n'égale jamais WM_LBUTTONDBLCLK

HELP ME :)

La taupe voit toujours tout (sauf les bugs)

12 réponses

Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
92
bon, un exemple
c'est plutot fait à la va-vite, mais l'essentiel est là :

matériel : un Form avec un label ^^

API (voir MSDN pour les infos sur les différents éléments) :
#region API : Méthodes

[DllImport("shell32.dll")]
private static extern bool Shell_NotifyIcon(
uint dwMessage,
[In] ref NOTIFYICONDATA pnid
);

#endregion

#region API : Structs

[StructLayout(LayoutKind.Sequential)]
private struct NOTIFYICONDATA 
{
public int cbSize;

public IntPtr hWnd;

public int uID;

public int uFlags;

public int uCallbackMessage;

public IntPtr hIcon;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] // 64 si < win 2000
public string szTip;

public int dwState;

public int dwStateMask;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public string szInfo;

public int uVersion;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
public string szInfoTitle;

public int dwInfoFlags;
}

#endregion

#region API : Constantes

private const int WM_MOUSEMOVE                    = 0x0200;
private const int WM_LBUTTONDOWN                  = 0x0201;
private const int WM_LBUTTONUP                    = 0x0202;
private const int WM_LBUTTONDBLCLK                = 0x0203;
private const int WM_RBUTTONDOWN                  = 0x0204;
private const int WM_RBUTTONUP                    = 0x0205;
private const int WM_RBUTTONDBLCLK                = 0x0206;
private const int WM_MBUTTONDOWN                  = 0x0207;
private const int WM_MBUTTONUP                    = 0x0208;
private const int WM_MBUTTONDBLCLK                = 0x0209;

private const int NIM_ADD         = 0x00000000;
private const int NIM_MODIFY      = 0x00000001;
private const int NIM_DELETE      = 0x00000002;

private const int NIF_MESSAGE     = 0x00000001;
private const int NIF_ICON        = 0x00000002;

private const int WM_APP       = 0x8000;

#endregion


Les methode d'ajout/suppression du NotifyIcon (ainsi que leur appel pour mon exemple : Load/Closing) et surtout le WndProc
private NOTIFYICONDATA nIconData;

private void ShellAddNotifyIcon()
{
Shell_NotifyIcon(NIM_ADD, ref nIconData);
}

private void ShellDeleteNotifyIcon()
{
Shell_NotifyIcon(NIM_DELETE, ref nIconData);
}

// override du WndProc de notre Form afin de traiter les messages qui nous interessent
protected override void WndProc(ref Message m)
{
if ( m.Msg == WM_APP + 0x1 )
{
// il s'agit d'un message associé à notre notifyicon, à nous de le traiter
switch ( (int)m.LParam )
{
case WM_LBUTTONDOWN:
// bouton gauche enfoncé
label_Status.Text = "WM_LBUTTONDOWN";
break;

case WM_LBUTTONUP:
// bouton gauche relaché
label_Status.Text = "WM_LBUTTONUP";
break;

case WM_LBUTTONDBLCLK:
// dblck bouton gauche
MessageBox.Show("Hello !!!");
break;
}
}
else
base.WndProc (ref m);
}

private void Form1_Load(object sender, System.EventArgs e)
{
ShellAddNotifyIcon();
}

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
ShellDeleteNotifyIcon();
}


et l'initialisation de la structure dans le constructeur du Form :
nIconData = new NOTIFYICONDATA();
nIconData.cbSize = Marshal.SizeOf(nIconData);
nIconData.hWnd = this.Handle;
nIconData.uID = 0;
nIconData.uFlags = NIF_ICON | NIF_MESSAGE;
nIconData.uCallbackMessage = WM_APP + 0x1;	// le message qui sera reçu pour identifier un message venant de notre notifyicon
nIconData.hIcon = this.Icon.Handle;			// icone de notre appli


je n'ai pas chercher a utiliser les specificités win 2000 et sup, j'espere que ça te permettra d'avancer pck tu etais vraiment partis de travers avec PeekMessage :-)

Cocoricoooooooo !!!!
coq
MVP Visual C#
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
92
je crois que tu es partis dans le mauvais sens là
d'apres ce que je sais uCallBackMessage te permet de specifier la valeur du message qui sera envoyé à ton appli (enfin, celle que tu as specifier en hwnd) et dont le lParam contiendra le type de message (WM_LBUTTONDBLCLK & co)
ce qui te permet de récupérer les messages associé à l'icone du systray et donc de les traiter

Cocoricoooooooo !!!!
coq
MVP Visual C#
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

D'accord Coq,

mais j'ai corrigé mes fautes que tu a données

Donc j'ai attribué a la notifyIcon WM_LBUTTONDBLCLK et j'ai attendu WM_LBUTTONDBLCLK avec une boucle while infinie

Regarde un peu mon code... La fonction PeekMessage donne toujours des zéros, zéros (d'après ce que j'ai vu sur MSDN) signifie qu'il y a rien dand la file d'attente... Et jamais la fonction donne autre chose que zéro...

Voici la procédure que j'ai modifiée

MSG message = new MSG();

while(true)
{

PeekMessage( ref message, this.Handle, 0, 0, 0);
if(message.lParam == 0x203)
{
MessageBox.Show("Oups");
}
}

Voilà, avec cette procédure j'attend un callback de valeur 0x203 (ou WM_LBUTTONDBLCLK), mais comment ca ce fait que je trouve toujours rien (retourne zéro). J'ai pas pu faire une erreur, j'ai regardé tout ce que MSDN pouvait me donner :sad)

La taupe voit toujours tout (sauf les bugs)
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

Ha l'API me donne toujours zéro...
Donc c'est bien une erreur de ma part...
Mais je ne vois pas...

La taupe voit toujours tout (sauf les bugs)
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
92
bon, laisse moi verifier 2-3 trucs et je te poste un bout de code

Cocoricoooooooo !!!!
coq
MVP Visual C#
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

D'accord coq, merci d'avance pour ton aide.

Si tu es interessé voici les pages de MSDN que j'ai trouvées

http://support.microsoft.com/default.aspx?scid=kb;en-us;74042
http://msdn.microsoft.com/...

Et un topic interessant (en anglais) sur la fonction PeekMessage pour le C#
http://www.gamedev.net/community/forums/topic.asp?topic_id=207360&forum_id=21

La taupe voit toujours tout (sauf les bugs)
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

Merci coq, tu m'offres une aide précieuse. Je vais passer en revue toute ta source pour ésperé comprendre les callbacks

La taupe voit toujours tout (sauf les bugs)
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

J'ai comrpis ce que tu a fait, mais dernière petite question, puis-je récupérer les message d'une fenêtre, en donnant simplement son Handle...
Parce que ma classe ne peut pas incorporer le
protected override void WndProc(ref Message m)
Puisque c'est depuis une autre classe que je recherche les message d'une fenêtre (je connais que sont handle). Es-ce que tu crois que le fonction peekMessage conviendrait?

La taupe voit toujours tout (sauf les bugs)
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
92
euh, tu veux dire quoi par là ?
tu utilises le code dans une classe ne derivant pas de Control directement ou indirectement et donc tu lui fournis le handle du form auquel est associé ton controle ?

Cocoricoooooooo !!!!
coq
MVP Visual C#
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

Voilà exactement, la seule chose que j'ai c'est le handle de la fenêtre d'ou l'icone dans le systray provient.

C'est justement pour ça, que peekMessage m'attirait. Dans l'API PeekMessage on peut fournire le handle, pour récupérer les CallBack de la fenêtre qui a ce Handle.

Mais cette fonction PeekMessage, ne me sort pas de message très "intéréssant".

Et voici ton code que j'ai retouché pour avec l'API PeekMessage (pour pouvoire choisire le handle de la windows), cette procédure est lancée dans un thread

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll")]
private static extern int PeekMessage(ref Message MessageOns, IntPtr windowHandle, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);

public void ecoute()
{

while(true)
{

if(PeekMessage( ref msg, this.Handle, 0, 0, 1 ) != 0)
{

// il s'agit d'un message associé à notre notifyicon, à nous de le traiter
switch ( (int)msg.Lparam)
{
case WM_LBUTTONDOWN; // bouton gauche enfoncé label_Status.Text = "WM_LBUTTONDOWN"; break;

case WM_LBUTTONUP: // bouton gauche relaché label_Status.Text = "WM_LBUTTONUP"; break;

case WM_LBUTTONDBLCLK; // dblck bouton gauche
MessageBox.Show("Hello !!!");
break;
}

}

}
}

La taupe voit toujours tout (sauf les bugs)
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
92
oula, laisse tomber PeekMessage je ne pense pas que tu puisses arriver à quoi que ce soit avec

à mon avis le mieux est que tu fasses deriver ta classe de la classe Control, et ainsi tu pourra fournir son Handle à nIconData.hWnd, mais aussi faire un override de WndProc pour traiter les messages, comme je le fesais avec le WndProc du Form

une autre methode serait de se servir directement de NativeWindow mais ça devient un peu plus compliqué

il me semble aussi qu'on peut "rediriger" la methode WndProc d'une fenetre mais là ça devient vraiment hasardeux

Cocoricoooooooo !!!!
coq
MVP Visual C#
Messages postés
150
Date d'inscription
samedi 31 janvier 2004
Statut
Membre
Dernière intervention
16 février 2009

Ha d'accord, je vais chercher et je te dis si je trouve.
Et encore merci pour ton aide précieuse.

La taupe voit toujours tout (sauf les bugs)