2010-12-13 30 views
3

J'ai le gestionnaire suivant de WndProc dans mon formulaire. Il convient d'empêcher le déplacement de la forme horizontalement (permettant de se déplacer verticalement seulement):Le gestionnaire WndProc est inefficace

protected override void WndProc(ref System.Windows.Forms.Message m) 
{ 
    if (!ShowCaption && m.Msg == 0x216) 
    { // Trap WM_MOVING 
     var rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 
     int w = rc.right - rc.left; 
     rc.left = this.Left; 
     rc.right = rc.left + w; 
     Marshal.StructureToPtr(rc, m.LParam, false); 
    } 
    base.WndProc(ref m); 
} 

Il fonctionne, mais lorsque l'utilisateur déplace l'augmentation très significative de l'utilisation sous forme de processeur. Qu'est-ce qui pourrait être si inefficace dans cette fonction et y a-t-il des façons de le faire?

+0

L'utilisation élevée du processeur n'est pas nécessairement une mauvaise chose. Est-ce réellement un problème, ou pourquoi cherchez-vous l'utilisation du processeur? http://blogs.msdn.com/b/oldnewthing/archive/2010/12/03/10097861.aspx –

+0

C'est vraiment un problème: cela provoque d'autres processus suspendus – SiberianGuy

+0

Une attribution est nécessaire à ce site. –

Répondre

2

J'ai essayé votre code, et ça marche bien. Il n'a pas saturé 100% CPU comme vous l'avez dit, seulement pris ~ 16%.

Je suppose que ce qui prend beaucoup de temps à traiter, c'est le dessin de votre formulaire, ou le dessin de vos fenêtres d'arrière-plan (et non l'implémentation de wndproc).

Essayez de limiter la quantité de redessine que votre formulaire peut faire par seconde en ajoutant une attente

System.Threading.Thread.Sleep(10); 

après cette ligne:

Marshal.StructureToPtr(rc, m.LParam, false); 

Sleeping 10 ms tout en faisant glisser les limites de votre formulaire de redessiner plus que 100 fois par seconde, tout en laissant un peu de CPU inutilisé ...

EDIT: J'ai oublié de mentionner que l'ajout du sommeil a changé le ~ 16% à ~ 12% sur ma boîte.

1

Vous pouvez simplement avaler le message si vous n'appelez base.WndProc dans votre bloc Si ​​

if (!ShowCaption && m.Msg == 0x216) 
{ 
    // Trap WM_MOVING 
} 
else 
{ 
    base.WndProc(ref m); 
} 

Une autre solution (fonctionne très bien, mais Somethimes scintille)

public partial class Form1 : Form 
{ 
    private int initialX; 
    public Form1() 
    { 
     InitializeComponent(); 
     initialX = this.Location.X; 
    } 

    private void Form1_LocationChanged(object sender, EventArgs e) 
    { 
     if (this.Location.X != initialX) 
      this.Location = new Point(initialX, this.Location.Y); 
    } 
} 
+0

Hm ... On dirait que ça n'aide pas – SiberianGuy

+0

Ajouté une autre solution –