FormBorderStyle issue - winforms

Encountered an issue with different FormBorderStyle modes. In 'None' mode everything works fine.
But as soon as I change the mode to anything else - this happens:
I'm getting strange empty area all around. Like the bounds are off on both axis
void InitializeComponent(void)
{
this->SuspendLayout();
//
// MainUI
//
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::None;
this->ClientSize = System::Drawing::Size(320, 250);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedToolWindow;
this->MaximizeBox = false;
this->MinimizeBox = false;
this->Name = L"MainUI";
this->Text = L"Dota 2 Efficiency Application";
this->ResumeLayout(false);
}
[STAThreadAttribute]
int Main(array<System::String ^> ^args){
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Creating a new form
MainUI^ form = gcnew MainUI();
// Creating a new ListView and adding it to the form
createList();
form->globalTimerInit();
form->Controls->Add(myGlobals::Globals::globalListView);
form->Controls->Add(myGlobals::Globals::labelForTimer);
Application::Run(form);
return 0;
}
When I'm trying to get Bounds and ClientRectangle of the Form it spits out this:
{X=0,Y=0,Width=336,Height=284}
{X=0,Y=0,Width=320,Height=250}
Looks like it's correct, but the area is way off.
Any advice?

I had multiple instances of __super::WndProc(m); and it resulted in this behavior.
ui.h
#include "stdafx.h"
////////////////////////HOTKEYS////////////////////////
protected: // Function that defines a hotkey
virtual void OnHandleCreated(EventArgs^ e) override {
__super::OnHandleCreated(e);
RegisterHotKey((HWND)this->Handle.ToPointer(), 1,
MOD_NOREPEAT, (UINT)Keys::NumPad3);
RegisterHotKey((HWND)this->Handle.ToPointer(), 2,
MOD_NOREPEAT, (UINT)Keys::NumPad2);
RegisterHotKey((HWND)this->Handle.ToPointer(), 3,
MOD_NOREPEAT, (UINT)Keys::NumPad1);
RegisterHotKey((HWND)this->Handle.ToPointer(), 4,
MOD_NOREPEAT, (UINT)Keys::NumPad0);
}
protected: // Function that executes code on hotkey
virtual void WndProc(Message% m) override {
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 1) {
//roshTimer();
}
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 2) {
//wardPurchased();
}
__super::WndProc(m);
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 3) {
//globalTimerStartPause();
}
__super::WndProc(m);
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 4) {
//reserved for future needs
}
__super::WndProc(m);
}
///////////////////////////////////////////////////////
stdafx.h
#pragma once
#include <Windows.h>
#pragma comment(lib, "user32.lib")

Related

WPF list modification during iteration?

I'm trying to make a very simple game where the yellow ball bouncing back and fourth. If it collides with one of the moving blue squares, the square is supposed to disappear and a new one should appear (always 3 in the window) elsewhere. When my code reaches this part, all 3 squares disappear (then reappears as intended it is not a problem) and I just cant figure out why. It would be a huge help if somebody could run over my methods responsible for the problem. Thank you in advance.
So my timer_Tick method, responsible for every frame:
void timer_Tick(object sender, EventArgs e)
{
logic.MoveBall();
if (model.Enemy.Count<3)
{
logic.AddEnemy();
}
int iii = 0;
foreach (MyShape enemy in model.Enemy) //the whole thing from here is me trying to solve list modification during iteration
{
if (logic.MoveEnemy(enemy) == -1)
{
logic.MoveEnemy(enemy);
}
else iii = logic.MoveEnemy(enemy);
}
if (iii > -1)
{
for (int j = model.Enemy.Count - 1; j >= 0; j--)
{
if (j == model.Enemy.Count - iii)
{
model.Enemy.RemoveAt(j);
}
}
}
}
MoveEnemy: I try to decide whether there is collusion and if yes, then try to remove the given shape object (blue square). Because This whole method is in a foreach, I just save the removable element and forward it to timer_Tick
public int MoveEnemy(MyShape shape)
{
int i = 0;
int ii = -1;
if ((shape.Area.IntersectsWith(model.Ball.Area)))
{
i = 0;
foreach (var e in model.Enemy)
{
i++;
if (shape == e)
{
ii = i;
}
}
}
shape.ChangeX(shape.Dx);
shape.ChangeY(shape.Dy);
bool coll = false;
foreach (var e in model.Enemy)
{
if ((e.Area.IntersectsWith(shape.Area)) && (shape != e))
{
coll = true;
}
}
if (shape.Area.Left < 0 || shape.Area.Right > Config.Width-40 || coll)
{
shape.Dx = -shape.Dx;
}
if (shape.Area.Top < 0)
{
shape.Dy = -shape.Dy;
}
if (shape.Area.Bottom > Config.Height/2)
{
shape.Dy = -shape.Dy;
}
RefreshScreen?.Invoke(this, EventArgs.Empty);
return ii;
}
And finally AddEnemy:
public void AddEnemy()
{
rnd = new Random();
int r = rnd.Next(-300, 300);
model.Enemy.Add(new MyShape(Config.Width / 2+r, 0, 40, 40));
RefreshScreen?.Invoke(this, EventArgs.Empty);
}
List<T> (or IList and Enumerable) exposes some useful methods to compact code:
int itemIndex = list.IndexOf(item); // Gets the index of the item if found, otherwise returns -1
list.Remove(item); // Remove item if contained in collection
list.RemoveAll(item => item > 5); // Removes all items that satisfy a condition (replaces explicit iteration)
bool hasAnyMatch = list.Any(item => item > 5); // Returns true as soon as the first item satisfies the condition (replaces explicit iteration)
A simplified version, which should eliminate the flaw:
void timer_Tick(object sender, EventArgs e)
{
if (model.Enemy.Count < 3)
{
logic.AddEnemy();
}
logic.MoveBall();
model.Enemy.ForeEach(logic.MoveEnemy);
model.Enemy.RemoveAll(logic.IsCollidingWithBall);
}
public void AddEnemy()
{
rnd = new Random();
int r = rnd.Next(-300, 300);
model.Enemy.Add(new MyShape(Config.Width / 2 + r, 0, 40, 40));
RefreshScreen?.Invoke(this, EventArgs.Empty);
}
public bool IsCollidingWithBall(MyShape shape)
{
return shape.Area.IntersectsWith(model.Ball.Area);
}
public int MoveEnemy(MyShape shape)
{
shape.ChangeX(shape.Dx);
shape.ChangeY(shape.Dy);
bool hasCollision = model.Enemy.Any(enemy => enemy.Area.IntersectsWith(shape.Area)
&& enemy != shape);
if (hasCollision || shape.Area.Left < 0 || shape.Area.Right > Config.Width - 40)
{
shape.Dx = -shape.Dx;
}
if (shape.Area.Top < 0)
{
shape.Dy = -shape.Dy;
}
if (shape.Area.Bottom > Config.Height / 2)
{
shape.Dy = -shape.Dy;
}
RefreshScreen?.Invoke(this, EventArgs.Empty);
}

Combining two instantiate scripts (Unity 3D)

I need to combine the following scripts into one script containing two functions, one that instantiates the next prefab in the array and the other that instantiates the previous prefab in the array (it is a virtual tour app). Both should also destroy the current prefab. I could then call the functions via event triggers.
I have this code for the "next Prefab" script.
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
if (gameObject.tag == "ArrowNEXT")
{
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
{
Destroy(currentObject);
currentIndex++;
if (currentIndex > Spheres.Length - 1) currentIndex = 0;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
}
}
I need to combine it with the following:
using UnityEngine;
public class RayCastPrevFIX: MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
if (gameObject.tag == "ArrowPREV")
{
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
{
Destroy(currentObject);
currentIndex--;
if (currentIndex < 0) currentIndex = Spheres.Length - 1;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
}
}
}
How would I go about this? Any help is greatly appreciated.I have this so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereSwap : MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void Next()
{
Destroy(currentObject);
currentIndex++;
if (currentIndex > Spheres.Length - 1) currentIndex = 0;
currentObject = Instantiate(Spheres[currentIndex]);
}
void Previous()
{
Destroy(currentObject);
currentIndex--;
if (currentIndex < 0) currentIndex = Spheres.Length - 1;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
You're on the right path, but you could shorten the code as well as use one function for both cases to avoid boilerplate:
using UnityEngine;
public class SphereSwap : MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
const string ArrowPrevTag = "ArrowPREV";
const string ArrowNextTag = "ArrowNEXT";
private void HandleClick(bool next)
{
if(Spheres == null || Spheres.Length == 0)
{
Debug.Log($"Spheres list is empty, nothing to swap.");
return;
}
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
// destroy current sphere.
Destroy(currentObject);
// go next or previous.
currentIndex += next ? 1 : -1;
// circular clamp if overflow
if (currentIndex < 0)
currentIndex = Spheres.Length - 1;
else if (currentIndex >= Spheres.Length)
currentIndex = 0;
// finally do instantiate.
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
private void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
{
// 'CompareTag' is more efficient than gameobject.tag == "sometag"
if (gameObject.CompareTag(ArrowNextTag))
HandleClick(true);
else if (gameObject.CompareTag(ArrowPrevTag))
HandleClick(false);
}
}
}

How do I repeat an action in c# to fix the jumping mechanism

I'm creating a basic 2D platformer game however the jumping mechanism will only run once and land directly afterwards. How do I loop this?
I tried detection collisions (from tag: Terrain) and this does help a lot however it's still not working correctly.
This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController2D : MonoBehaviour
{
private Rigidbody2D rb2D;
private Vector2 velocity;
Vector2 xvelocity = new Vector2(10, 0);
Vector2 yvelocity = new Vector2(0, 10);
public float jumptime;
bool grounded = true;
bool jump = false;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetButton("Jump"))
{
jump = true;
}
}
private void FixedUpdate()
{
//Debug.Log(Input.GetAxisRaw("Vertical"));
if (left == true)
{
//Debug.Log("Left");
rb2D.MovePosition(rb2D.position + -xvelocity * Time.fixedDeltaTime);
}
if (right == true)
{
//Debug.Log("Right");
rb2D.MovePosition(rb2D.position + xvelocity * Time.fixedDeltaTime);
}
//if (jump == true && grounded == true)
//{
// jumptime -= Time.fixedDeltaTime;
// if (jumptime > 0)
// {
// rb2D.MovePosition(rb2D.position + yvelocity * Time.fixedDeltaTime);
// }
// if (jumptime <= 0)
// {
// jump = false;
// jumptime = 2;
// }
if (jump == true && grounded == true && jumptime > 0)
{
jumptime -= Time.fixedDeltaTime;
rb2D.MovePosition(rb2D.position + yvelocity * Time.fixedDeltaTime);
} else if (jumptime <= 0)
{
jump = false;
jumptime = 2f;
}
//if (Time.fixedDeltaTime >= 2)
//{
// jump = false;
// rb2D.MovePosition(rb2D.position + -yvelocity * Time.fixedDeltaTime);
//}
}
void OnCollisionExit2D(Collision2D other)
{
Debug.Log("No longer in contact with " + other.transform.name);
jump = true;
grounded = false;
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Terrain")
{
Debug.Log("Landed");
jump = false;
grounded = true;
}
}
}
The expected outcome is that the action 'jump' will loop for ~1/1.5 seconds with a good height (vector2 yvelocity) so it will jump higher and will come down afterwards (thanks to the gravity from the Rigidbody (2D))
As stated in the comments I think the main issue is coming from this line of code.
if (jump == true && grounded == true && jumptime > 0)
It is much likely that one of those bool is not what you expect it to be. Anyway I suggest you to convert the line like so:
if (jump && grounded && jumptime > 0)
You do not need == true for booleans.
Anyway, to solve your question in an easier way, I would suggest you to use AddForce instead of move (because you're using a rigibody2d anyway).
rb2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
A small note about horizontal velocity. If you're using a rigibody it would be better to move it with the same rigidbody and not with the transform:
rb2D.MovePosition(rb2D.position + Vector2.left * xspeed * Time.fixedDeltaTime);
Your code will become:
public class PlayerController2D : MonoBehaviour
{
private Rigidbody2D rb2D;
private Vector2 velocity;
public float jumpForce = 5;
bool grounded = true;
void Start() { rb2D = GetComponent<Rigidbody2D>(); }
void Update()
{
if (Input.GetButton("Jump") && grounded)
rb2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
//calculate horizontal speed here
xspeed = ...;
}
private void FixedUpdate()
{
rb2D.MovePosition(rb2D.position + Vector2.left * xspeed * Time.fixedDeltaTime);
}
void OnCollisionExit2D(Collision2D other)
{
Debug.Log("No longer in contact with " + other.transform.name);
grounded = false;
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Terrain")
{
Debug.Log("Landed");
grounded = true;
}
}
}

Playing sound parallelly with System.Media.SoundPlayer.PlaySync() and AxWindowsMediaPlayer

I have created a WinForm application which contains an AxWMPLib.AxMediaPlayer in which I play some videos. I also have to play some other custom sounds in a different thread. For this I used System.Media.SoundPlayer.PlaySync(). This thread plays couple of sound files sequentially in a loop. The problem is when I pause/stop the video the button event sounds are played fine. But when the video is running, sometimes some of the sound files are skipped. And it happens randomly.
Could anyone give some explanation about the problem and how to over come it. I mean how could I play the both sounds and video in parallel.
The video is playing in the UI thread and the other sounds are playing from different thread.Please check out the code bellow:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using ElectroQ;
using ElectroQServer1.Entities;
using WMPLib;
using System.Media;
using System.Windows.Media;
namespace ElectroQServer1
{
public partial class Form1 : Form
{
Thread dbListenerThread;
IWMPPlaylist playlist;
//string[] tokenNumber = { "A001", "B002", "C003", "D004","E005", "F006", "G007","HAMB" };
//string[] counterNumber = { "01", "02", "03", "04", "05", "06", "07", "MB" };
public Form1()
{
InitializeComponent();
//ResizeRedraw = true;
this.SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer, true);
this.WindowState = FormWindowState.Maximized;
//this.FormBorderStyle = FormBorderStyle.None;
//this.TopMost = true;
dbListenerThread = new Thread(RefreshQueueBoard);
dbListenerThread.Start();
}
/// <summary>
/// This method is used to prevent the flickering of the window.
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
public void RefreshQueueBoard()
{
//Thread.Sleep(000);
while (true)
{
List<QueueData> lstQData = DA.GetAllQueueData(" where service_status_id = 2 ");
printToken(lstQData);
printCounter(lstQData);
playSound(lstQData);
Thread.Sleep(1000);
}
}
public void playSound(List<QueueData> lstQData)
{
foreach (QueueData qData in lstQData)
{
if (!qData.SoundPlayed)
{
string strSoundFile;
PlaySoundFIle(#"Sounds/TN.WAV");
foreach (char c in qData.ServiceQueueSerial)
{
strSoundFile = string.Format(#"Sounds/{0}.WAV", c);
PlaySoundFIle(strSoundFile);
}
PlaySoundFIle(#"Sounds/CN.WAV");
foreach (char c in qData.ServiceCounterID)
{
strSoundFile = string.Format(#"Sounds/{0}.WAV", c);
PlaySoundFIle(strSoundFile);
}
string strUpdateQuery = string.Format("UPDATE electro_queue SET sound_played = 1 WHERE service_queue_serial = '{0}'", qData.ServiceQueueSerial);
DA.UpdateQueueData(strUpdateQuery);
}
}
}
public void PlaySoundFIle(string strFile)
{
//string[] files = new string[4] { #"Sounds/TN.WAV", #"Sounds/CN.WAV", #"Sounds/TN.WAV", #"Sounds/CN.WAV"};
//WaveIO wa = new WaveIO();
//wa.Merge(files, #"tempfile.wav");
//MediaPlayer wowSound = new MediaPlayer(); //Initialize a new instance of MediaPlayer of name wowSound
//wowSound.Open(new Uri(#"tempfile.wav", UriKind.Relative)); //Open the file for a media playback
//wowSound.Play();
using (var soundPlayer = new SoundPlayer(strFile))
{
soundPlayer.PlaySync(); // can also use soundPlayer.Play() but it misses some sound file.
}
}
private void printToken(List<QueueData> lstQData)
{
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate
{
pnlQStat.Controls.Clear();
string dir;
//int xpos = 55;
//int ypos = 207;
int xpos = 10;
int ypos = 00;
//int k=0;
for (int i = 0; i < lstQData.Count; i++)
{
/* if (i == 4 || i == 8)
{
ypos = ypos - 360;
xpos = 675;
}*/
foreach (char c in lstQData[i].ServiceQueueSerial)
{
if (i == 0)
{
dir = "Resources/_" + c + ".bmp";
}
else
{
dir = "Resources/" + c + ".bmp";
}
createPicBox(dir, "pBox" + i, xpos, ypos);
xpos = xpos + 43;
}
ypos = ypos + 50;
xpos = 10;
}
}));
return;
}
}
private void printCounter(List<QueueData> lstQData)
{
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate
{
//int xpos = 415;
//int ypos = 207;
//int xpos = 292;
int xpos = 220;
int ypos = 00;
//int k=0;
for (int i = 0; i < lstQData.Count; i++)
{
/*if (i == 4 || i == 8)
{
ypos = ypos - 360;
xpos = 1035;
}
*/
foreach (char c in lstQData[i].ServiceCounterID)
{
string dir;
if (i == 0)
{
dir = "Resources/_" + c + ".bmp";
}
else
{
dir = "Resources/" + c + ".bmp";
}
//string dir = "Resources/" + c + ".bmp";
createPicBox(dir, "pBox" + i, xpos, ypos);
xpos = xpos + 63;
}
ypos = ypos + 50;
xpos = xpos - 63;
}
}));
return;
}
}
private void createPicBox(string directory, string name, int xposition, int yposition)
{
PictureBox picBox = new System.Windows.Forms.PictureBox();
picBox.Name = name;
picBox.Location = new System.Drawing.Point(xposition, yposition);
picBox.Size = new System.Drawing.Size(40, 50);
picBox.BackgroundImage = Image.FromFile(directory);
picBox.BackgroundImageLayout = ImageLayout.Stretch;
pnlQStat.Controls.Add(picBox);
}
private void Form1_Load(object sender, EventArgs e)
{
createPlayList();
//dbListenerThread.Abort(); // this line of code should be placed in onClosing Event.
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
dbListenerThread.Abort();
player.playlistCollection.remove(playlist);
}
private void createPlayList()
{
playlist = player.playlistCollection.newPlaylist("mpl");
playlist.appendItem(player.newMedia(#"E:\SONGS\teri-meri-promo-Muskurahat.Com.wmv"));
playlist.appendItem(player.newMedia(#"E:\MOVZZZ\English\The Kid\THE KID FILM_1_0001.avi"));
player.currentPlaylist = playlist;
}
private void btnPlay_Click(object sender, EventArgs e)
{
// player.URL = #"E:\MOVZZZ\English\The Kid\THE KID FILM_1_0001.avi";
player.Ctlcontrols.play();
}
private void btnStop_Click(object sender, EventArgs e)
{
player.Ctlcontrols.stop();
}
}
}
My objective is to play the looped sound files sequentially with the video playing in parallel.
You should not use SoundPlayer for this purpose; SoundPlayer is a lightweight, convenience class for playing occasional incidental sounds in an application. It will occasionally skip sounds if other things are going on in the audio subsystem (like a video playing). Here is a good sample that shows how to use the low-level waveOutOpen API for playing sounds.

wpf richtextbox check if caret is in the last line or count how many lines it has

I am trying to find out in a richtext box whether the caret is position in the last line. Is this possible?
NOTE: At the end I also added: or count how many lines it has, this is because in the miscrosoft forum there is an example for detecting in which line the caret is.
thanks
Please verify the msdn link
http://social.msdn.microsoft.com/Forums/en/wpf/thread/667b5d2a-84c3-4bc0-a6c0-33f9933db07f
If you really wanted to know the line number of the caret, you could do something like the following (probably needs some tweaking):
TextPointer caretLineStart = rtb.CaretPosition.GetLineStartPosition(0);
TextPointer p = rtb.Document.ContentStart.GetLineStartPosition(0);
int caretLineNumber = 1;
while (true)
{
if (caretLineStart.CompareTo(p) < 0)
{
break;
}
int result;
p = p.GetLineStartPosition(1, out result);
if (result == 0)
{
break;
}
caretLineNumber++;
}
The code to get the number of lines:
Int32 CountDisplayedLines(RichTextBox rtb)
{
Int32 result = -1;
rtb.CaretPosition = rtb.Document.ContentStart;
while (rtb.CaretPosition.GetLineStartPosition(++result) != null)
{
}
return result;
}
I have found a solution. Maybe there is a simpler way, if so please let me know
private void OnHasRtbReachedEnd(System.Windows.Controls.RichTextBox rtb)
{
TextPointer pointer1 = rtb.CaretPosition;
int iCurrentLine = GetLineNumber(rtb);
rtb.CaretPosition = rtb.Document.ContentEnd;
int iLastLine = GetLineNumber(rtb);
if (iCurrentLine == iLastLine)
{
if (!_bIsRtbMovingUpDown)
MoveToNextDataGridRow();
_bIsRtbMovingUpDown= false;
}
else
{
_bIsRtbMovingUpDown= true;
}
rtb.CaretPosition = pointer1;
}
//This code comes from
//http://social.msdn.microsoft.com/Forums/en/wpf/thread/667b5d2a-84c3-4bc0-a6c0-33f9933db07f
private int GetLineNumber(System.Windows.Controls.RichTextBox rtb)
{
TextPointer caretLineStart = rtb.CaretPosition.GetLineStartPosition(0);
TextPointer p = rtb.Document.ContentStart.GetLineStartPosition(0);
int caretLineNumber = 1;
while (true)
{
if (caretLineStart.CompareTo(p) < 0)
{
break;
}
int result;
p = p.GetLineStartPosition(1, out result);
if (result == 0)
{
break;
}
caretLineNumber++;
}
return caretLineNumber;
}
I tried the code and is not giving correct results always.
One smart way to do it is this
int previousCursorPosition;
private void RichTarget_KeyDown_1(object sender, KeyEventArgs e)
{
if (e.Key == Key.Up || e.Key == Key.Down)
{
Xceed.Wpf.Toolkit.RichTextBox rich = (Xceed.Wpf.Toolkit.RichTextBox)sender;
previousCursorPosition = rich.CaretPosition.GetOffsetToPosition(rich.CaretPosition.DocumentStart);
}
}
private void RichTextBox_KeyUp_1(object sender, KeyEventArgs e)
{
if (e.Key == Key.Up)
{
Xceed.Wpf.Toolkit.RichTextBox rich = (Xceed.Wpf.Toolkit.RichTextBox)sender;
if (previousCursorPosition == rich.CaretPosition.GetOffsetToPosition(rich.CaretPosition.DocumentStart))
{
//do your staff
}
}
else if (e.Key == Key.Down)
{
Xceed.Wpf.Toolkit.RichTextBox rich = (Xceed.Wpf.Toolkit.RichTextBox)sender;
if (previousCursorPosition == rich.CaretPosition.GetOffsetToPosition(rich.CaretPosition.DocumentStart))
{
//do your staff
}
}
}

Resources