Pictures that behave as symbols in textbox (or something like textbox) - c#

I need to create a control, that behaves like a textbox, but allows you to replace some (or all) of the characters with pictures that behave (select and remove with backspace/delete) as a normal characters.
I tried to create a RichTextBox inherited control, with "CanPaste - Paste" construction, but the images added this way didn't act like the characters, but as the images which can be resized. It's not a correct solution for me.
So, the question is: How can I override "symbol drawing" method? I mean, get actual (x,y) coordinates of drawing character, and draw picture instead of it (or in front of it). Is that possible?
Control should look similar to this picture. (lockers on picture are images, acting like symbols.)
UPD: Control must be working on systems from XP to 8, so using UTF-8 lock-style symbol won't be a solution for me. Control shown on the screenshot above works in an application that is running on a Windows XP — though I have no idea which way it was implemented.

What I would is use a PasswordBox with a FontFamily="Segoe UI Symbol" and the PasswordChar="& # xE14D;" (remove the spaces). This will render this:
The complete code: <PasswordBox Password="Example" Width="100" FontFamily="Segoe UI Symbol" PasswordChar="" />

Related

Looking for a way to create/replace custom controls + Border

I'd like to create an application with exactly the same titlebar / controls as in Visual Studio. Or do you know dnSpy? It is using them as well.
https://prnt.sc/j731zj
I also like to have this 1px border, the blue one in this case.
I already googled alot, also tried to find something here, but I'm not finding anything helpful for me.
Here for example (it's from Wallpaper Engine) the window not only has that blue border, which I like to have, it has some kind of a blue shadow as well? Which looks pretty cool to me. I'd like to try that as well.
https://prnt.sc/j7321n
What I already tried in WinForms is working with panels and create it on my own.
https://prnt.sc/j73bj5
I managed to get the border that I want, I also could use pictureboxes for the min/max/close buttons?
But that's not exactly what I was looking for, I also have to code the move/drag behaviour of the app too then, since there is no controls anymore. Which is not that hard but... I want it another way.
Anyone can help me with that? I'm using C# in VS 2017 and I'd like to create the app either with Forms or WPF. Probably going for WPF.
Almost forgot to mention I don't really want to use 3rd party tools like MahApps, Metro Framework, etc.. Isn't there a build-in metro style option in VS or something? Rather in .NET framework.
I mean it's actually only these 3 buttons, min/max/close. And the border. That's all I need
It's quiet simple , if you wanna drag the window , make use of the DragMove method :
private void WhatEverControlYouWanttoUseToClickAndDrag_MouseDown()
{
DragMove();
)
The rest
You can simply use Image control.You can add any image you want to display.Put it above a Rectangle and use it.
Explanation
Image control comes from the System.Windows.Controls namespace.Rectangle control is no different.Now, you might ask ,why am i not suggesting Button ? Well, you can use a button but you cannot achieve your required looks with it unless you go with ControlTemplate,which,for a beginner, i would not suggest at all.
You can use a Rectangle,set a Fill color.Now, what if you want to change the color when the mouse is over the rect ? Well, here's a sample XAML that'll also add an animation to the color-changing :)
<Rectangle >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Fill" Value = "Blue" Duration="0:0:0.3"/>
///Add required closing tags please
Now, about the Image control.When you place it over the rectangle , you need to set the IsHitTestVisible property to False which will prevent any sort of mouse interaction on/with it which will also prevent the interference between the Image and the Rectangle. :)
One last tip , if you want to have the Image control apply the clearest look/best quality on the image,make sure to set BitmapScalingMode to Fant :
<Image Source="\ac.png" RenderingOptions.BitmapScalingMode="Fant"/>

WPF - Multiline TextBox text gets blurry while typing a long text

I have a textBox that grows vertically while typing. Unfortunately when I type a long text (for example a 3 line text) some PART of it gets blurry. What's more, when I prevent it from growing vertically and make it grow horizontally it works fine - the text is sharp then.
What I've tried:
UseLayoutRounding = true;
RenderOptions.TextRenderingMode = "ClearType";
Please forget about
TextOptions.TextFormattingMode = "Display"
It has to be "Ideal".
See the screenshots:
Disable SubPixel Rendering and Anti-Aliasing. Try
SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
Since you mentioned:
I have a textBox that grows vertically while typing
I assume then that it's a CustomControl derived from TextBox and with a custom rendering to grow vertically instead of using the builtin text wrap ability.
Since I was unable to reproduce your issue with the stock TextBox and the parameters (with Ideal) you mentioned (I've checked from Framework 4.0 to 4.6 on VS 2013), maybe the blur comes from your custom code.
By the way, with not using the builtin wrap?
TextWrapping="Wrap"
Maybe you should include more code and details, like framework version, visual studio version, OS version and so on.
Likewise, specify your version of "Textbox that grows vertically". Something like this ?
Try increasing the font size of the textbox just a tiny amount (use 1/4s if in pixels). Alternatively, try changing the line height slightly in a similar fashion. I think the problem might be down to WPF's interpretation of the sub-pixels and may be rounding off at the wrong place.

Why do I have have to use UIElement.UpdateLayout?

We have a rather large WPF business application and I am working on a retool of an existing WPF FixedPage/FixedDocument report.
It's a somewhat busy ecosystem. We have a built-in forms generator, with lots of different controls you can put on (think like a mini built-in visual studio). All that works fine. You fill in the form on the screen, and then you can print out (to XPS) the identical copy to standard 8.5x11 paper.
In the code, we break out this report into vertical chunks. Say each chunk would be an inch or two tall on a printed piece of paper. This is how we handle pagination. If the next chunk is too tall for the page, we do a NewPage() and repeat. As I mentioned, this was working fine.
WPF has an enormous learning curve and I've been going back over old code and refactoring things and happily working with DataTemplates, strongly typed ViewModels, and generic ContentControls in order to reduce the size of our code. The on-screen forms generator still works, but the FixedDocument report has gotten weird.
Going back to those vertical slices, we print the user's forms to paper as individual Grid controls. Nothing fancy. Each grid (as I mentioned above) may be an inch or two high, containing any random mixture of checkboxes, radiobuttons, textblocks, and so on.
When the grids contained these stock (standard) MS WPF controls, I could do this all day long:
System.Windows.Controls.Grid g = .....
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
And get back proper sizes, i.e. 100 x 67.
Now, sometimes the grids have just one control - a header if you will (i.e. "This Month's Schedule). The only child control added to that grid is a ContentControl.
The ContentControl is simply bound to a ViewModel:
<ContentControl Content="{Binding}" />
There's then two DataTemplates in the resource dictionary that picks up this binding. Here, I'll show that:
<UserControl.Resources>
<w:MarginConverter x:Key="boilerMargin" />
<DataTemplate DataType="{x:Type render:BoilerViewModel}">
<render:RtfViewer
Width="{Binding Path=Width}"
TextRTF="{Binding Path=Rtf}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type render:Qst2NodeViewModel}">
<ContentControl Content="{Binding Path=BoilerVm}">
<ContentControl.Margin>
<MultiBinding Converter="{StaticResource boilerMargin}">
<Binding Path="NodeCaptionVm.Height" />
<Binding Path="NodeLeft" />
</MultiBinding>
</ContentControl.Margin>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
The ContentControl will pick up that bottom-most datatemplate. That template will then in turn use the smaller one above.
The fancy converter just sets a margin. It may be fugly to read, but this all displays correctly on the screen within the parent usercontrol. It's all the right size and justification and all that.
On the printed report side (XPS), I have to create these controls in code and measure them to see if they'll fit on the current FixedPage. When I go to do this step: (on the grid containing this ContentControl)
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
I get back 0,0 size. Even though it should be like 730x27 for instance. Again, on the screen, hosted in a UserControl, this all works fine. Just trying to instantiate it and measure it purely in code fails. I've confirmed that the control is added to the grid, has its row and col set, has been added to the Children collection, etc...
If I prepend those two statements with an UpdateLayout call, like this, then it works:
g.UpdateLayout(); //this fixes it
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
I've been reading that UpdateLayout is expensive and to be avoided, and I'd rather not be calling this on each grid section before I add it to my FixedPage of the FixedDocument report. There could be dozens or even hundreds of iterations. And, again, if the Grid has regular WPF controls in it, without any ContentControls and fancy finding and looking up datatemplates, the measuring works fine without the UpdateLayout call.
Any advice? Thank you!
I just don't understand why it became necessary to start calling it once I started utilizing the Xaml engine. It almost feels like I'm being punished for using the advanced features.
Its complicated to explain that but let me try using plain words... In wpf everything works with dispatcher. Futhermore like you may already know dispatcher deals with tasks ordered by priority.
For example first a control is being initalized, then binding is being triggered, then values are updated, in the end all that is being measured.. etc etc
What you managed somehow is by setting all those contentcontrol inside contentcontrol stuff, you screwed up that order
Calling UpdateLayout basically forces dispatcher to finish its pending work in layout so you can work with clean layout afterwards
Screwing with dispatcher is quite common in wpf since some controls or values may be added later which ends in remeasuring things.
In your case you seem to be creating all at once in one method call without letting dispatcher take a breath. Therefore you need UpdateLayout method to normalize dispatchers queue.
I hope this helps you. You can also solve your issue by using Dispatcher.BeginInvoke.
UpdateLayout does not work in my case. I had to wait until dispatcher finishes processing of the layout tasks.
toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Application.Current.Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
I found another article about this approach.

Formatting Text in a ListView?

I'm creating a little app that will read, parse, and format the contents of a lua script - specifically, a SavedVariables file from World of Warcraft created by the "Elephant" chat logging add-on. The prototype I have in mind will generate an array of ListViewItem instances, showing a timestamp, player name, what channel the message was posted into, and the message that was posted.
I'd like to have the chat message rendered as it would be in the game: the game colors the names of those "talking" in the chat after their character's class (e.g. a rogue's name is yellow, mages' names are light blue), but when it comes to ListViewItem and ListViewSubItem, coloring text there seems to be an all-or-nothing deal.
Would it be possible to add functionality for the ListView to apply formatting (or just color) to text in a ListViewItem or ListViewSubItem based on markup in the Text property?
EDIT: I'm asking if it's possible to just add text formatting to a ListViewItem through the magic of inheritance/polymorphism in a derived class, and if so, what's the best way to do it (amount of effort, code security, etc)?
Speaking from a Windows Forms usage view point, you can render the items manually. However you should also consider situations such as: how should the text be rendered when the text exceeds the bounds of the Control/column?
This only requires that you inherit from ListView; you can render each item using:
protected override void OnDrawItem(DrawListViewItemEventArgs e)
Of course, OwnerDraw must be set to true. DrawListViewItemEventArgs contains the text that needs to be rendered and the Graphics instance that should be used to render the text. You could then use DrawString(string s, Font font, Brush brush, float x, float y) to render each part of the text as required by your mark-up convention.
If you don't mind the GPL, ObjectListView does offer more formatting options but perhaps it is not as flexible as you require.
Since a RichTextBox does allows flexible text formatting, I wonder if it could somehow be used as a renderer...
im not completely sure this would work and I cant really test it, but it might be worth a try
<ListViewItem>
<ContentPresenter>
<TextBlock>
<Run x:Name="playerName" Foreground="Blue" Text="NAME"/>
<Run x:Name="etc" Foreground="Black" Text="..."/>
</TextBlock>
</ContentPresenter>
</ListViewItem>
The basic idea here is that in the list box item you have a the content presenter that I think holds the textblock. Within this you can set individual Run tags (bits of individual text) and you can format each one differently. you should also be able to set the text programmatically when the run tags are assigned names

Text update slowing down app

I have a Hebrew calendar app where each day is a UserControl. I have 6 labels in that control for the English date, the Hebrew date, Jewish holidays and some other user-defined data. When scrolling, the labels' content changes as the date value for the UserControl goes up or down a week. The scrolling is noticeably slower than Microsoft Outlook Calendar, and profiling reveals that the part taking the longest is updating the label contents, which is not handled by my code.
Is there some way I can make this go faster? MS Outlook seems to have a comparable number of text fields, and the scrolling is smooth.
TextBlocks were not noticeably faster than Labels, but Glyphs gave my calendar whiplash.
Replacing this
<TextBlock Padding="5"
FontFamily="Narkisim"
FontWeight="Bold"
FontSize="20"
Text="{Binding HebrewDate}"/>
with this
<Glyphs Name="HebrewDate"
Margin="5"
StyleSimulations="BoldSimulation"
FontUri = "/Fonts/nrkis.ttf"
FontRenderingEmSize = "20"
UnicodeString = "5771 ןושח ה"
Fill = "Black"/>
made scrolling super fast.
Some notes:
Glyphs do not support binding, so I had to give each one a name and update them in the code behind, like so:
HebrewDate.UnicodeString = zman.HebrewDate;
Glyphs don't have Layout functionality so Hebrew text was coming out backwards. I had to preprocess the Hebrew strings with a reversing function. Even after reversing, the Hebrew vowel points came out misaligned, so I retained Labels for those strings which use vowels.
I can't be sure but it is possible that MS Outlook was coded in something faster than WPF, perhaps using DirectX to show the graphics rapidly.
Otherwise I might suggest toning down on the number of bindings updating at once, I would suggest using an additional thread to gradually update the labels as and when there are spare cycles instead of all at once, which might be causing your stuttering.
To go along with the previous answer, I recommend the background worker. Utilize the background worker for your most time consuming operation that gets executed during the scroll.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Categories