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ą wposition
- w metodzie
Draw()
rysujemy w miejscu wskazanym przezposition
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)
Jako, ż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();
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:
Jeż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
.
Jedna odpowiedź Zostaw komentarz