|
Did you see this Thumb controls[^] ? You don't seem to have the resizing Thumb in your Template.
|
|
|
|
|
You right. I must look for some tutorial, how to use Thumb control and implement into my code. THX lot
|
|
|
|
|
The article I mentioned has it implemented.
|
|
|
|
|
Again... THX LOT! It works.
modified on Thursday, March 12, 2009 6:14 AM
|
|
|
|
|
Hello,
i´m trying to write a WPF User Control that looks like a matrix of LEDs.
I´ve created a RenderTargetBitmap over a DrawingVisual that looks like a matrix of quadratic dots.
The problem is that, when using the control, the dots are not displayed quadratic. The dots are displayed rectangular instead and very small.
I´ve also saved the created matrix bitmap in a bmp file. The matrix bitmap is correctly displayed if it is opened with a standard program.
How can i change rendering, so that the pixel of the matrix bitmap are displayed correctly?
In the past i´ve created such a matrix bitmap with MFC and BitBlt, ther was no such blur, if the bitmap was displayed by a control.
I used the following code in my control:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
namespace TestWpf
{
public partial class MyControl : UserControl
{
private const double INCH_PER_UNIT = 1.0 / 96.0;
private const int BMP_DPI = 96;
private const double PIXEL_RAD = 1;
private const double PIXEL_SPACE = 1;
private static readonly Brush PIXEL_OFF_BRUSH = new SolidColorBrush(Color.FromRgb(150, 150, 150));
private static readonly Brush PIXEL_BACKGND_BRUSH = new SolidColorBrush(Colors.Black);
RenderTargetBitmap _pixelOffBmp;
RenderTargetBitmap _matrixBmp;
public MyControl()
{
InitializeComponent();
_pixelOffBmp = CreatePixelBmp(PIXEL_OFF_BRUSH);
_matrixBmp = CreateMatrixBmp();
SaveBmp(_matrixBmp);
}
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawImage(_matrixBmp, new Rect(0, 0, _matrixBmp.Width, _matrixBmp.Height));
}
RenderTargetBitmap CreatePixelBmp(Brush pixBrush)
{
double unitWidth, unitHeight;
unitWidth = 2 * PIXEL_RAD;
unitHeight = unitWidth;
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext dc = drawingVisual.RenderOpen())
{
dc.DrawRectangle(pixBrush, null, new Rect(0, 0, unitWidth, unitHeight));
}
int pixelWidth, pixelHeight;
pixelWidth = (int)(BMP_DPI * unitWidth * INCH_PER_UNIT);
pixelHeight = (int)(BMP_DPI * unitHeight * INCH_PER_UNIT);
RenderTargetBitmap bmp = new RenderTargetBitmap(pixelWidth, pixelHeight, BMP_DPI, BMP_DPI, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
bmp.Freeze();
return bmp;
}
RenderTargetBitmap CreateMatrixBmp()
{
int xMatrixPixel = 20 * 6;
int yMatrixPixel = 2 * 8;
double xUnitsMatrixBmp = xMatrixPixel * (2 * PIXEL_RAD + PIXEL_SPACE) + PIXEL_SPACE;
double yUnitsMatrixBmp = yMatrixPixel * (2 * PIXEL_RAD + PIXEL_SPACE) +PIXEL_SPACE;
int pixelWidthMatrixBmp = (int)(BMP_DPI * xUnitsMatrixBmp * INCH_PER_UNIT);
int pixelHeightMatrixBmp = (int)(BMP_DPI * yUnitsMatrixBmp * INCH_PER_UNIT);
this.Width = xUnitsMatrixBmp + BorderThickness.Left + BorderThickness.Right;
this.Height = yUnitsMatrixBmp + BorderThickness.Top + BorderThickness.Bottom;
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext dc = drawingVisual.RenderOpen())
{
dc.DrawRectangle(PIXEL_BACKGND_BRUSH, null, new Rect(0, 0, xUnitsMatrixBmp, yUnitsMatrixBmp));
double xOffset = 0;
double yOffset = PIXEL_SPACE;
for (int y = 0; y < yMatrixPixel; y++)
{
xOffset = PIXEL_SPACE;
for (int x = 0; x < xMatrixPixel; x++)
{
dc.DrawImage(_pixelOffBmp, new Rect(xOffset, yOffset, _pixelOffBmp.Width, _pixelOffBmp.Height));
xOffset += _pixelOffBmp.Width + PIXEL_SPACE;
}
yOffset += _pixelOffBmp.Height + PIXEL_SPACE;
}
}
RenderTargetBitmap bmp = new RenderTargetBitmap(pixelWidthMatrixBmp, pixelHeightMatrixBmp, BMP_DPI, BMP_DPI, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
bmp.Freeze();
return bmp;
}
void SaveBmp(BitmapSource bmpSource)
{
BmpBitmapEncoder bmp = new BmpBitmapEncoder();
bmp.Frames.Add(BitmapFrame.Create(bmpSource));
using (Stream stm = File.Create("foo.bmp"))
{
bmp.Save(stm);
}
}
}
}
Thanks,
Andy
|
|
|
|
|
This problem occurs due to WPFs resolution independence and most noticible with images like your example. An overview is at http://msdn.microsoft.com/en-us/library/aa970908.aspx and if you search with terms like "wpf pixel snapping" you'll find a lot of blog posts about the subject.
In the end I got your example working with a rather crude method.
public MyControl()
{
InitializeComponent();
RenderOptions.SetBitmapScalingMode(this,BitmapScalingMode.NearestNeighbor);
_pixelOffBmp = CreatePixelBmp(PIXEL_OFF_BRUSH);
_matrixBmp = CreateMatrixBmp();
SaveBmp(_matrixBmp);
LayoutUpdated += (s, e) => InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
var pos = this.PointFromScreen(this.PointToScreen(new Point(0, 0)));
double x = pos.X - Math.Floor(pos.X);
double y = pos.Y - Math.Floor(pos.Y);
drawingContext.DrawImage(_matrixBmp, new Rect(1-x,1-y, _matrixBmp.Width, _matrixBmp.Height));
}
If you just want a repeating pattern ImageBrush might be what your after.
You may want to rethink your approach if you want to get the best out of WPF. For example each LED could be an individual control laid out inside a UniformGrid and have its appearance change using data binding. This sudoku tutorial might give you some ideas although I don't know what your control is going to display, I was thinking along the lines of a graph/audio spectrum.
|
|
|
|
|
Thanks a lot for your anwser, it helps a lot.
The matrix bitmap is now correctly displayed.
To update the LEDs, i use a second bitmap, the _contentBmp, with the same size as the matrix bmp.
Now the matrix bmp is copied into the content bmp and for each LED whch is on, a bmp that represent the on status is copied into the content bmp.
The content bmp is now used in the OnRender().
A timer in the main window sets and resets the LEDs every 200 milli seconds:
MyCtrl.PixelEnabled = !MyCtrl.PixelEnabled
RenderTargetBitmap _pixelOffBmp;
RenderTargetBitmap _pixelGreenBmp;
RenderTargetBitmap _matrixBmp;
RenderTargetBitmap _contentBmp;
int _xMatrixPixel;
int _yMatrixPixel;
double _xUnitsMatrixBmp;
double _yUnitsMatrixBmp;
private bool _pixelEnabled = false;
public bool PixelEnabled
{
get { return _pixelEnabled; }
set
{
_pixelEnabled = value;
UpdateDisplay();
}
}
RenderTargetBitmap CreateMatrixBmp()
{
......
RenderTargetBitmap bmp = new RenderTargetBitmap(pixelWidthMatrixBmp, pixelHeightMatrixBmp, BMP_DPI, BMP_DPI, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
bmp.Freeze();
_contentBmp = new RenderTargetBitmap(pixelWidthMatrixBmp, pixelHeightMatrixBmp, BMP_DPI, BMP_DPI, PixelFormats.Pbgra32);
return bmp;
}
void UpdateDisplay()
{
RenderTargetBitmap pixelBmp;
if (!PixelEnabled) pixelBmp = _pixelOffBmp;
else pixelBmp = _pixelGreenBmp;
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext dc = drawingVisual.RenderOpen())
{
dc.DrawImage(_matrixBmp, new Rect(0, 0, _xUnitsMatrixBmp, _yUnitsMatrixBmp));
double xOffset = 0;
double yOffset = PIXEL_SPACE;
for (int y = 0; y < _yMatrixPixel; y++)
{
xOffset = PIXEL_SPACE;
for (int x = 0; x < _xMatrixPixel; x++)
{
if (x % 5 == 0)
dc.DrawImage(pixelBmp, new Rect(xOffset, yOffset, pixelBmp.Width, pixelBmp.Height));
xOffset += pixelBmp.Width + PIXEL_SPACE;
}
yOffset += pixelBmp.Height + PIXEL_SPACE;
}
}
_contentBmp.Render(drawingVisual);
}
protected override void OnRender(DrawingContext drawingContext)
{
var pos = this.PointFromScreen(this.PointToScreen(new Point(0, 0)));
double x = pos.X - Math.Floor(pos.X);
double y = pos.Y - Math.Floor(pos.Y);
drawingContext.DrawImage(_contentBmp, new Rect(1-x, 1-y, _contentBmp.Width, _contentBmp.Height));
}
Now the problem is that the CPU usage is about 50%!
The cause that the LayoutUpdated Event calls InvalidateVisual().
But without calling InvalidateVisual() the Bitmap is not correctly displayed if the size of the main window is changed by user.
The Sudoku sample is very interesting and i will study it exactly by the next opportunity.
But i´m skeptic about the performance.
Earlier than the approach with bitmaps, i´ve created a LED matrix with Shapes and that takes a lot of performance.
I like to create the LED matrix for simulating a LED Display, which can display text and graphic, the text can flash or it can by marquee text etc.
The size of the display can be 240 x 48 pixel, so i have 11520 controls.
|
|
|
|
|
That is probably too many controls.
I just tried a few other methods for the offset that I thought might work but they produced artifacts.
Overlaying an ImageBrush of the gridlines on to normal content might be good enough or you could try writing a custom pixel shader. The one below is based on PixelateEffect but puts gaps inbetween. Shazzam is quite handy.
float HorizontalPixelCounts : register(C0);
float VerticalPixelCounts : register(C1);
sampler2D implicitInputSampler : register(S0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 brickCounts = { HorizontalPixelCounts, VerticalPixelCounts };
float2 brickSize = 1.0 / brickCounts;
float2 brickNum = floor(uv / brickSize);
float2 centerOfBrick = brickNum * brickSize + brickSize / 2;
float2 edge = uv - (brickNum * brickSize);
if(edge.x < 0.01 || edge.y < 0.01)
{
return float4(0,0,0,0);
}
return tex2D(implicitInputSampler, centerOfBrick);
}
|
|
|
|
|
Thanks for the hint about PixelShader.
I´ve played around with the Pixel Shader Effects Library, it´s very interesting.
The test of your 'GapEffect' shows, that the gaps are not equally spaced.
I´m not familiar with that HLSL, so i can´t test if the gaps can made equally spaced by adjusting the PixelShader or if there is no chance to do this with PixelShader.
It seems to me that to learn HLSL is very time-consuming.
It´s a little bit frustrating that a new technology like WPF, which can do much comlex things with a few commands makes a lot of problems by doing such basic things like drwing rectangles with defined size. These things are not complex to do with older technologies.
|
|
|
|
|
Hi,
I'm trying to bind an own made attached property but I can't get it to work. I know how to do it with a normal dependency property and I have found help on the internet that concerns canvas attached properties but that isn't exactly what I need.
XAML code:
<Button Tooltip="Edge Color" IsEnabled="{Binding Path=(SCOLOR), ElementName=nsifCanvas, Mode=OneWay, Converter={StaticResource convGraphicColour}}">
<Image Source="Resources\Icons\LineColorHS.png" Style="{StaticResource IconStyle}"/>
</Button>
Next is my attached property. The value in it comes from an enum "GraphicColour". That enum just contains 2 values (for the moment) that defines the kind of colorscheme a graphic has: C (colored) and M (monochrome). I want that a button on my GUI gets disabled if I select a "graphic" (actually a UIElement) that is monochrome (value "M"). When the value is "C", the button must be enabled so the user can select a color. So I want that the button gets enabled or disables depending on the graphic I have selected at the moment. With the code I have now, the button just stays disabled! The converter in XAML converts the enum value to a boolean (true if graphic can contain colors, else false).
/// <summary>
/// Graphic color.
/// </summary>
public static readonly DependencyProperty SCOLORProperty;
/// <summary>
/// Get graphic SCOLOR.
/// </summary>
public static GraphicColour GetSCOLOR(Annotation graphic)
{
return (GraphicColour)graphic.GetValue(SCOLORProperty);
}
/// <summary>
/// Set graphic SCOLOR.
/// </summary>
public static void SetSCOLOR(Annotation graphic, GraphicColour value)
{
graphic.SetValue(SCOLORProperty, value);
}
static NSIFCanvas()
{
SCOLORProperty = DependencyProperty.RegisterAttached(
"SCOLOR",
typeof(GraphicColour),
typeof(NSIFCanvas),
new PropertyMetadata(GraphicColour.M));
}
I have no idea how to connect the enable propertie of the button to that attached property of the graphic selected on the moment. Is this possible and do you maybe have an example? (I can set and get the property value in code for a certain graphic.)
Thanks!
|
|
|
|
|
Does your converter get called and with the proper values ? I am suspecting databinding problem to the canvas object. Did you see in the output window if you get any databinding errors logged ? I couldn't run your example, it says Annotation does not have a SetValue/GetValue.
Secondly, you might be having a reason, but the scenario you have mentioned would be covered with a normal dependency property, why do you want to make it an attached property ?
|
|
|
|
|
The converter only gets called when the program starts. GetSCOLOR never gets called. The biggest problem is that I don't exactly know how to bind an attached property so I guess that is the problem. I don't get any errors.
Annotation is a control that I wrote to contain graphics (rectangles, circles, ... drawn by the user). That control gets added to a canvas (nsifCanvas) multiple times. Every annotation control has the property SCOLOR (so some can be monochrome and other can contain colors). That is the reason why I use an attached property. When I click on an annotation, that one gets active and depending on the property, a button in a toolbar must be enabled (if the annotation can contain colors) or disabled (monochrome annotation).
Next is a part of the XAML code. In nsifCanvas the user can add Images and also Annotations (the control where the user can add graphics). Everything works except the binding to the attached property.
<Grid>
<DockPanel>
<!-- Add toolbar tray to window -->
<ToolBarTray DockPanel.Dock="Top" Orientation="Horizontal" IsLocked="False">
<!-- tbTools -->
<ToolBar Name="tbTools" Band="1" BandIndex="1">
<Button ToolTip="Edge Color" IsEnabled="{Binding Path=(SCOLOR), ElementName=nsifCanvas, Mode=OneWay, Converter={StaticResource convGraphicColour}}">
<Image Source="Resources\Icons\LineColorHS.png" Style="{StaticResource IconStyle}"/>
</Button>
</ToolBar>
</ToolBarTray>
<!-- Window -->
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<controls:NSIFCanvas x:Name="nsifCanvas" Background="LightGray">
<!-- Add children in code to populate canvas -->
</controls:NSIFCanvas>
</ScrollViewer>
</DockPanel>
</Grid>
So, I guess I am correct to use an attached property? And if it is correct, does anybody has an example how to bind it? I guess the binding needs to contact the Get function but like I said, the way I do it now, the program doesn't get there. The elementname in the binding is nsifCanvas. nsifCanvas contains the property but the property depends on the annotation control that is a child of that canvas.
I hope someone has an example or something.
Thx
|
|
|
|
|
Ok, here are my thoughts on this.
Pauwels Bart wrote: don't exactly know how to bind an attached property so I guess that is the problem
I think the binding syntax is correct.
"The value which an element has for an attached property is stored by that element, not by the element which exposes the attached property." - Josh Smitt[^]
Relating to your scenario. You would have the SCOLOR attached property in each of the Annotation object. And I am sure that is not what you are expecting ?
What you want is, SCOLOR behave like a "SelectedItem" or "SelectedColor". I would suggest, make a dependency property named "SelectedAnnotation" in your Canvas which will hold the currently selected Annotation object. When an annotation object is selected, set this DP to the selected annotation object.
Bind the button to the SelectedItem property in NFSICanva. Something like this,
IsEnabled="{Binding Path=SelectedAnnotation.SCOLOR , ElementName=nsifCanvas, Mode=OneWay, Converter={StaticResource convGraphicColour}}"
Pauwels Bart wrote: GetSCOLOR never gets called.
Take a look here Debugging dependency properties[^]
|
|
|
|
|
Sorry, I told it wrong. I don't have an attached property in each Annotation object. The attached property is in the nsifCanvas. That was the reason why I used an attached property: every element on the canvas can then have its own value for that property.
Offcourse only the Annotation Control must have that property! Thanks to you I now realise that my solution (an attached property on the nsifCanvas) was not good. Now I have made a normal property in the Annotation control itself (the only control that needs that property).
I allready have a dependency property in nsifCanvas that contains the active element. This is from the type UIElement. The active element can be (at the moment) an image OR an annotation control OR null when noting is selected. Do you maybe know if I can use this property for the binding or do I need to make a new one of the type Annotation? And what do I get when the active element is an image and not an annotation (in this case the buttons also need to be disabled). I guess that when the value of the active element property is "null", the binding will just make the button enabled (null.SCOLOR).
Sorry for the new questions. My normal bindings work perfect but this goes a little bit further and at the moment I'm just a little confused with it all. You have helped me a lot allready, THX ABitSmart!!!
|
|
|
|
|
You can bind to the dependency property directly (instead of DP.SCOLOR) and in your converter you can decide based on the type what should be returned. The converter should be invoked when you set the DP to null also.
Pauwels Bart wrote: THX ABitSmart!!!
Welcome :>
|
|
|
|
|
Offcourse!!!!! So simple! I made it much harder then it was.
Again, thx a lot!
|
|
|
|
|
Hi, from what i know i can use WPF to create browser app using C# code.
My question is , can a WPF application (that is to be viewed from internet browser),be accessed from a central server by many clients over the internet/intranet(intranet is my case),so that users don't need to install the app(except they must have prerequisite .net framework 3/3.5)
I am asking this because i have not learnt ASP.NET yet,so want to see if WPF is better AND future alternative.
-Thanks
|
|
|
|
|
Yes - take a look at ClickOnce deployment.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys
|
|
|
|
|
Thanks for reply , will look at it now.
|
|
|
|
|
I've been messing around with Silverlight for the last week, trying to get a handle on Prism v2 which was released recently and I had some struggles working with the WCF client proxy generated by Visual Studio. I was trying to use the interface which was generated so I wouldn't have any service dependencies when it was time to write tests. I think the result has been a pretty good implementation, and since I had trouble finding a lot of recommendations on it I wrote a blog post about it. I'd appreciate any feedback as I'm looking to use Silverlight in an upcoming project and I'd like to know if I'm getting things right or if there are some problems I haven't seen yet.
Here's the link to the blog post: http://developmentalmadness.blogspot.com/2009/03/silverlight-and-prism-decoupling-wcf.html[^]
|
|
|
|
|
Hello,
I have a problem with my TreeView not showing the vertical scrollbar correctly. I have plain old TreeView without any kind of style, item template or anything. If I add so many items that they start to appear past the TreeView window, I get a vertical scroll bar. This is pretty standard stuff, I know. But the problem is that the scrollbar itself is strange. Both the up/down scroll bar buttons, which are usually located at the top and bottom of the scrollbar, both appear at the top. Plus, there's no scroll bar thumb between them. I don't know why this is happening. In the design window, the scrollbar is normal.
I just find it strange since my tree view is so basic.
Any ideas?
Thanks!
|
|
|
|
|
Mine just works noraml. Are you setting any styles ?? might be the reason.
|
|
|
|
|
As I mentioned, there are no styles or anything applied to my tree view.
Here's an example as basic as I can make it.
<Window x:Class="TestProject.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window7" Height="119" Width="92"
xmlns:local="clr-namespace:TestProject.Breeze">
<TreeView Name="_treeView1">
<TreeViewItem Header="Employee1 Very Long String">
<TreeViewItem Header="Jesper"/>
<TreeViewItem Header="Aaberg"/>
<TreeViewItem Header="12345"/>
</TreeViewItem>
<TreeViewItem Header="Employee2">
<TreeViewItem Header="Dominik"/>
<TreeViewItem Header="Paiha"/>
<TreeViewItem Header="98765"/>
</TreeViewItem>
</TreeView>
</Window>
I'm absolutely stumped. And it occurs on my collegues' computers as well.
|
|
|
|
|
Do you see the horizontal scrollbar? What happens if you stretch the window horizontally, and then expand the treeview? I've just run your sample and it behaves the way I'd expect it to - you see the small vertical scrollbar because there's a horizontal scrollbar taking up space.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys
|
|
|
|
|
I fiddled a bit with my code and found the cause, even though I don't really understand why.
My application uses a directx renderer from a DLL that's written in C++. To init the renderer, I pass it the WPF window's hwnd by using WindowInteropHelper. Now the interesting bit: If I init the renderer before creating and showing my modeless dialogs (the ones with the scrollbar problem), the scrollbars don't appear correctly. But if I init the renderer *after* creating the dialogs, the scrollbars are fine.
If anyone has an idea of why this happens, I'd be happy to hear it!
|
|
|
|
|