Okiełznać mysz w XNA + WF

Podstawowym elementem zaznaczania jest ustalenie pozycji myszy na ekranie. Przy pracy nad tą funkcjonalnością pewien delikatny niuans sprawił, że zajęło to zdecydowanie dłużej, niż zakładałem.

Mysz w XNA

Dobranie się do pozycji myszy w czystym XNA jest niezmiernie łatwo. Służy do tego obiekt klasy MouseState, który wypełniamy bieżącymi informacjami fragmentem kodu:

MouseState mouseState = Mouse.GetState();

Po wykonaniu takiej operacji obiekt mouseState zawiera aktualną pozycję myszy (pola X oraz Y), stan przycisków (lewy, prawy, środkowy – stany wciśnięty lub nie) oraz np. wartość rolki (Scroll). Sprawdzenie tego będzie proste:

  • do klasy dodajemy pole Vector2 position;
  • w metodzie Update() pobieramy pozycję myszy i zapamiętujemy ją w position
  • w metodzie Draw() rysujemy w miejscu wskazanym przez position krzyż oznaczający kursor: . Skorzystamy tu z informacji z poprzedniego wpisu do załadowania tekstury.

w metodzie LoadContent()

cursor = Content.Load<Texture2D>("Textures\\cursor");

w metodzie Update()

private Vector2 position;

protected override void Update(GameTime gameTime)
{
    MouseState ms = Mouse.GetState();
    position = new Vector2(ms.X, ms.Y);
}

metoda Draw()

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    Vector2 textureCenter = new Vector2(cursor.Width / 2.0f, cursor.Height / 2.0f);
    spriteBatch.Draw(cursor, position, null, Color.White, 0.0f, textureCenter, 1.0f, SpriteEffects.None, 0.0f);
    spriteBatch.End();

    base.Draw(gameTime);
}

Efekt zastosowania powyższego kodu widać na obrazku poniżej (UWAGA, jest to kod TYLKO dla XNA, bez umieszczania renderingu na formie Windows Forms)

Kursor 1Jako, że ani PrintScreen ani Fraps nie rejestrują kursora myszy przy robieniu screenshot’a będę go zaznaczał czerwoną kropką.

Ten sam kod zastosujmy przy użyciu Windows Forms – rendering odbywa się na formie, pozycja kursora odczytywana jest przez Mouse.GetState();

Kursor 2Houston, we have a problem..

Mysz z Windows Forms

Rozwiązaniem okazało się użycie pozycji myszy pobranej z Windows Forms, z przetransformowaniem jej do współrzędnych okna. Stworzyłem drugą teksturę (czerwony krzyżyk), aby wyświetlić ją w miejscu obliczonym drugim sposobem i do porównania wyników, kod poniżej:

w metodzie LoadContent()

redCursor = Content.Load<Texture2D>("Textures\\cursor2");

w metodzie Update()

private Vector2 position;
private Vector2 wfPosition;

protected override void Update(GameTime gameTime)
{
    MouseState ms = Mouse.GetState();
    position = new Vector2(ms.X, ms.Y);

    System.Drawing.Point mousePos = form.PointToClient(Form.MousePosition);
    wfPosition = new Vector2(mousePos.X, mousePos.Y);
}

metoda Draw()

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    Vector2 textureCenter = new Vector2(cursor.Width / 2.0f, cursor.Height / 2.0f);
    spriteBatch.Draw(cursor, position, null, Color.White, 0.0f, textureCenter, 1.0f, SpriteEffects.None, 0.0f);
    spriteBatch.Draw(redCursor, wfPosition, null, Color.White, 0.0f, new Vector2(redCursor.Width, redCursor.Height), 1.0f, SpriteEffects.None, 0.0f);
    spriteBatch.End();

    base.Draw(gameTime);
}

Efekt poniżej:

Kursor 3Jeżeli dokładnie nie widać czerwonej kropki – jest ona w okolicach środka czerwonego krzyża 😉

Podsumowanie

Przy zaznaczaniu będzie trzeba zastosować podejście łączone – pozycję myszy pobierać przy użyciu Windows Forms (Form.MousePosition + Form.PointToClient()) natomiast informacje o wciśnięciu przycisku z obiektu MouseState.

Be Sociable, Share!
czoper opublikowano dnia 2010-9-26 Kategoria: Daj się poznać, Programowanie, Theme Festival | Tagi:, ,

Jedna odpowiedź Zostaw komentarz

    Zostaw odpowiedź

    (Ctrl + Enter)