Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
in HTML everything you do can be zoomed in or out (usually the browser supports this feature), I want to accomplish something similar in WPF. Is that possible? If so, how?
As Ed Plunkett suggested you can use a ScaleTransform.
For example you can apply a different ScaleTransform depending on how the user moves the mouse wheel:
public partial class MainWindow : Window
{
private double currentZoomFactor = 1;
public MainWindow()
{
InitializeComponent();
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
base.OnMouseWheel(e);
FrameworkElement content = Content as FrameworkElement;
if (content != null)
{
if (e.Delta > 0)
{
currentZoomFactor += .1;
content.LayoutTransform = new ScaleTransform(currentZoomFactor, currentZoomFactor);
}
else
{
currentZoomFactor -= .1;
currentZoomFactor = Math.Max(.1, currentZoomFactor);
content.LayoutTransform = new ScaleTransform(currentZoomFactor, currentZoomFactor);
}
}
}
}
Moving the wheel up makes a zoom in; viceversa wheel down makes a zoom out. I hope it can help you.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
This is a little guide to help resolve a problem with timers that stops when opening a file using process to open it with the default application.
If you are using a timer in C# WPF you will notice that the timer will stop working until the file has been closed which may not be the behavior that you want.
Let say for instance that you want a timer to start as soon as the file you want to show to the user is open. While the user sees or read the file you want the timer to continue. Without using a Thread the timer will not continue it's work up until the file is closed.
This is the problem encountered:
I have a timer that is started by pressing a button (btnTache1) but it stops when I'm using System.Diagnostics.Process to open a file with it's default application using another button (btnVideo1). It only resume after the file is closed.
This a brief description of the components of the program:
There is a button to show the media called btnVideo1
The onclick event of the button defines a timer _timer1 and the file to show to the user _media1 and a countdown used by the timer _startingTimer1 set to 30 seconds.
Here is the code:
private int _startingTimer1;
private string _media1;
DispatcherTimer _timer1 = new DispatcherTimer();
private void btnVideo1_Click(object sender, RoutedEventArgs e)
{
_startingTimer1 = 30; // 30 seconds
// stop timer if already started
if (_timer1.IsEnabled == true)
{
_timer1.Stop();
}
// configure timer
_timer1 = new DispatcherTimer();
_timer1.Interval = TimeSpan.FromSeconds(1);
_timer1.Tick += timer_Tick1;
_timer1.Start();
// defining the file to show to the user
string procedure = "procedure1.mp4"
_media1 = "//10.10.0.1/Procedures/ + procedure;
ShowVideo(_media1);
}
// Action done when a tick for timer occur
private void timer_Tick1(object sender, EventArgs e)
{
// decreasing countdown
_startingTimer1--;
// calculate and show the timer (countdown)
TimeSpan time = TimeSpan.FromSeconds(_startingTimer1);
tbxTemps1.Text = time.ToString();
// if timer under 0
if (_startingTimer1 < 0)
{
// change background color depending on number
if (_startingTimer1 % 2 == 0)
btnTemps1.Background = new SolidColorBrush(Colors.OrangeRed);
else
btnTemps1.Background = new SolidColorBrush(Colors.LightGray);
}
}
// show the file to the user
private void ShowVideo(string media)
{
try
{
// define a process to show the file
System.Diagnostics.Process process = new System.Diagnostics.Process();
// declare the path to the file
process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
process.StartInfo.UseShellExecute = true;
// start the process to show the file to the user
process.Start();
process.WaitForExit();
}
catch
{
MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
To resolve the issue the use of a Thread really comes handy. Calling the function using a thread makes the timer continue in the primary thread while other things are done in parallel in another thread. To achieve this here's what I have changed.
I changed the ShowVideo method as follow:
private void ShowVideo(string media)
{
try
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
process.StartInfo.UseShellExecute = true;
Thread showFile = new Thread(() => process.Start());
showFile.Start(); // start the Thread
showFile.Join();
showFile.WaitForExit();
}
catch
{
MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to remove dotted focus rectangle from my custom Tab Control. I've tried everything and I could not remove that rectangle.
As you can see in the picture, the focus rectangle is disturbing in my application design.
Please help!
To remove the focus cue, you have to set UserPaint to true, and then paint the entire tab control yourself, including the borders, text, backgrounds, highlighting, hot-tracking, etc.
The following code only paints the tab text and the background:
public class TC2 : TabControl {
public TC2() {
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
var g = e.Graphics;
TabPage currentTab = this.SelectedTab;
for (int i = 0; i < TabPages.Count; i++) {
TabPage tp = TabPages[i];
Rectangle r = GetTabRect(i);
Brush b = (tp == currentTab ? Brushes.LightSteelBlue : Brushes.LightGray);
g.FillRectangle(b, r);
TextRenderer.DrawText(g, tp.Text, tp.Font, r, tp.ForeColor);
}
}
protected override void OnPaintBackground(PaintEventArgs e) {
base.OnPaintBackground(e);
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm new to Flash and intermediate in HTML/CSS. I would like to create a grid of buttons that when you hover over them, they change color and show a linkable caption/tooltip on hover. I would also like this to be dynamic as possible as I will need a grid of 2000+ buttons/squares that may have to be updated from time to time.
Here is an example created with HTML/CSS and some JS
//<![CDATA[
$(window).load(function(){
// Create the tooltips only when document ready
$(document).ready(function () {
// This will automatically grab the 'title' attribute and replace
// the regular browser tooltips for all <a> elements with a title attribute!
$('a[title]').qtip();
});
});//]]>
I need to know the best way to build this in flash, and would really appreciate a barebones breakdown of the code/AS. I am somewhat new to flash and this is just way above my head.
Thanks in advance.
Ok, so you want grid of small bitmaps/shapes on stage. I would recommend bitmaps since they work better when you want to transform something - but if the grid will be standing still, then you can use Sprite filled with color. Below you can find a snippet complete example. You can compile it using mxmlc compiler or using Flash Develop||FDT, or connecting this file as a document class in Flash IDE.
It's the most efficient way I can imagine. We have only one Sprite and we color some parts of it depending on where our mouse is. Hope this helps.
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* #author
*/
public class Main extends Sprite
{
private var color:int = 0xf2f2f2;
private var color1:int = 0xff000;//colors definition
private var size:int = 12;//size of our square
private var container:Sprite;//container definition
private var rows:int = 48;//number of rows
private var margin:int = 2;//margin on each side
private var count:int = 2000;//number of elements
private var totalspace:int = size + margin;
private var currentPoint:Point = new Point();
private var lastPoint:Point = null;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
container = new Sprite();//define squares container;
container.graphics.beginFill(color);//define fill color;
var posX:int;
var posY:int;
for ( var i:int = 0; i < count; i++) {
posX = int(i % rows) * totalspace;//calculate x axis position based on modulo
posY = int(i / rows) * totalspace;//calculate y axis position
container.graphics.drawRect( posX, posY, size, size );//call drawRect method on graphics object.
}
addChild(container);//add container to stage - meaning it will be visible, because flash is rendering it.
container.buttonMode = true;//set mouse to button mode
container.addEventListener( MouseEvent.MOUSE_MOVE, onMM );
container.addEventListener( MouseEvent.ROLL_OUT, onMO );
//add eventListener for mouse move - so each time you move a mouse over container object it will trigger an event.
}
private function onMO(e:MouseEvent):void
{
currentPoint = null;
}
private function onMM(e:MouseEvent):void
{
if ( lastPoint == currentPoint ) {
//if moouse is on the same square exit this function
return;
}
//calculate x and y position of square we need to color
currentPoint = new Point( int( container.mouseX/totalspace ) * totalspace, int(container.mouseY/totalspace) * totalspace );
container.graphics.beginFill( color1 );
container.graphics.drawRect( currentPoint.x, currentPoint.y, size, size );
if ( lastPoint ) {
//if last point is present, make it grey, as for roll out
container.graphics.beginFill( color );
container.graphics.drawRect( lastPoint.x, lastPoint.y, size, size );
}
lastPoint = currentPoint;
}
}
}
In this case when user click some UIElement I want this element yo be surrounded by dashed border. If there is some other object surrounded then this code removes it first.
Everything is fine but "private void activateElem" fires twice and I have no idea why. Maybe somebody can help, I really have no more ideas.
Anybody knows some ideas to debug issues like this? Maybe there is some way to print out all events queue. There is silverlight spy but I think it doesn't work for windows phone 7.
My code:
public class ManipulationEngine
{
private Canvas sheet;
private static FrameworkElement current_active_element;
public ManipulationEngine(Canvas sheet)
{
this.sheet = sheet;
foreach (FrameworkElement elem in sheet.Children)
{
elem.MouseLeftButtonUp += new MouseButtonEventHandler(activateElem);
}
}
private void activateElem(object sender, MouseButtonEventArgs e)
{
FrameworkElement elem = sender as FrameworkElement;
if (current_active_element != null)
{
desactivateElem();
}
Grid grid = new Grid();
Rectangle recentagle = new Rectangle();
grid.SetValue(Canvas.TopProperty, (double)elem.GetValue(Canvas.TopProperty) - 10);
grid.SetValue(Canvas.LeftProperty, (double)elem.GetValue(Canvas.LeftProperty) - 10);
DoubleCollection stroke = new DoubleCollection();
stroke.Add(4);
stroke.Add(2);
recentagle.StrokeDashArray = stroke;
grid.Children.Add(recentagle);
sheet.Children.Remove(elem);
elem.Margin = new Thickness(10);
grid.Children.Add(elem);
sheet.Children.Add(grid);
current_active_element = elem;
}
private void desactivateElem()
{
if (current_active_element != null)
{
Grid grid = VisualTreeHelper.GetParent(current_active_element) as Grid;
grid.Children.Remove(current_active_element);
sheet.Children.Remove(grid);
current_active_element.SetValue(Canvas.TopProperty, (double)grid.GetValue(Canvas.TopProperty) + 10);
current_active_element.SetValue(Canvas.LeftProperty, (double)grid.GetValue(Canvas.LeftProperty) + 10);
current_active_element.Margin = new Thickness(0);
sheet.Children.Add(current_active_element);
current_active_element = null;
}
}
I'd really advise looking into the Parts and States model. You may be able to do this with a button, or perhaps a radio button.
Usually if you're coding changes to the visual tree, you're not doing it right.
Karen Corby dealt with this very clearly at MIX08, take a look!
http://archive.visitmix.com/blogs/2008Sessions/T20/
Luke
For a System.Windows.Forms.TextBox with Multiline=True, I'd like to only show the scrollbars when the text doesn't fit.
This is a readonly textbox used only for display. It's a TextBox so that users can copy the text out. Is there anything built-in to support auto show of scrollbars? If not, should I be using a different control? Or do I need to hook TextChanged and manually check for overflow (if so, how to tell if the text fits?)
Not having any luck with various combinations of WordWrap and Scrollbars settings. I'd like to have no scrollbars initially and have each appear dynamically only if the text doesn't fit in the given direction.
#nobugz, thanks, that works when WordWrap is disabled. I'd prefer not to disable wordwrap, but it's the lesser of two evils.
#André Neves, good point, and I would go that way if it was user-editable. I agree that consistency is the cardinal rule for UI intuitiveness.
I came across this question when I wanted to solve the same problem.
The easiest way to do it is to change to System.Windows.Forms.RichTextBox. The ScrollBars property in this case can be left to the default value of RichTextBoxScrollBars.Both, which indicates "Display both a horizontal and a vertical scroll bar when needed." It would be nice if this functionality were provided on TextBox.
Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form. It's not quite perfect but ought to work for you.
using System;
using System.Drawing;
using System.Windows.Forms;
public class MyTextBox : TextBox {
private bool mScrollbars;
public MyTextBox() {
this.Multiline = true;
this.ReadOnly = true;
}
private void checkForScrollbars() {
bool scroll = false;
int cnt = this.Lines.Length;
if (cnt > 1) {
int pos0 = this.GetPositionFromCharIndex(this.GetFirstCharIndexFromLine(0)).Y;
if (pos0 >= 32768) pos0 -= 65536;
int pos1 = this.GetPositionFromCharIndex(this.GetFirstCharIndexFromLine(1)).Y;
if (pos1 >= 32768) pos1 -= 65536;
int h = pos1 - pos0;
scroll = cnt * h > (this.ClientSize.Height - 6); // 6 = padding
}
if (scroll != mScrollbars) {
mScrollbars = scroll;
this.ScrollBars = scroll ? ScrollBars.Vertical : ScrollBars.None;
}
}
protected override void OnTextChanged(EventArgs e) {
checkForScrollbars();
base.OnTextChanged(e);
}
protected override void OnClientSizeChanged(EventArgs e) {
checkForScrollbars();
base.OnClientSizeChanged(e);
}
}
I also made some experiments, and found that the vertical bar will always show if you enable it, and the horizontal bar always shows as long as it's enabled and WordWrap == false.
I think you're not going to get exactly what you want here. However, I believe that users would like better Windows' default behavior than the one you're trying to force. If I were using your app, I probably would be bothered if my textbox real-estate suddenly shrinked just because it needs to accomodate an unexpected scrollbar because I gave it too much text!
Perhaps it would be a good idea just to let your application follow Windows' look and feel.
There's an extremely subtle bug in nobugz's solution that results in a heap corruption, but only if you're using AppendText() to update the TextBox.
Setting the ScrollBars property from OnTextChanged will cause the Win32 window (handle) to be destroyed and recreated. But OnTextChanged is called from the bowels of the Win32 edit control (EditML_InsertText), which immediately thereafter expects the internal state of that Win32 edit control to be unchanged. Unfortunately, since the window is recreated, that internal state has been freed by the OS, resulting in an access violation.
So the moral of the story is: don't use AppendText() if you're going to use nobugz's solution.
I had some success with the code below.
public partial class MyTextBox : TextBox
{
private bool mShowScrollBar = false;
public MyTextBox()
{
InitializeComponent();
checkForScrollbars();
}
private void checkForScrollbars()
{
bool showScrollBar = false;
int padding = (this.BorderStyle == BorderStyle.Fixed3D) ? 14 : 10;
using (Graphics g = this.CreateGraphics())
{
// Calcualte the size of the text area.
SizeF textArea = g.MeasureString(this.Text,
this.Font,
this.Bounds.Width - padding);
if (this.Text.EndsWith(Environment.NewLine))
{
// Include the height of a trailing new line in the height calculation
textArea.Height += g.MeasureString("A", this.Font).Height;
}
// Show the vertical ScrollBar if the text area
// is taller than the control.
showScrollBar = (Math.Ceiling(textArea.Height) >= (this.Bounds.Height - padding));
if (showScrollBar != mShowScrollBar)
{
mShowScrollBar = showScrollBar;
this.ScrollBars = showScrollBar ? ScrollBars.Vertical : ScrollBars.None;
}
}
}
protected override void OnTextChanged(EventArgs e)
{
checkForScrollbars();
base.OnTextChanged(e);
}
protected override void OnResize(EventArgs e)
{
checkForScrollbars();
base.OnResize(e);
}
}
What Aidan describes is almost exactly the UI scenario I am facing. As the text box is read only, I don't need it to respond to TextChanged. And I'd prefer the auto-scroll recalculation to be delayed so it's not firing dozens of times per second while a window is being resized.
For most UIs, text boxes with both vertical and horizontal scroll bars are, well, evil, so I'm only interested in vertical scroll bars here.
I also found that MeasureString produced a height that was actually bigger than what was required. Using the text box's PreferredHeight with no border as the line height gives a better result.
The following seems to work pretty well, with or without a border, and it works with WordWrap on.
Simply call AutoScrollVertically() when you need it, and optionally specify recalculateOnResize.
public class TextBoxAutoScroll : TextBox
{
public void AutoScrollVertically(bool recalculateOnResize = false)
{
SuspendLayout();
if (recalculateOnResize)
{
Resize -= OnResize;
Resize += OnResize;
}
float linesHeight = 0;
var borderStyle = BorderStyle;
BorderStyle = BorderStyle.None;
int textHeight = PreferredHeight;
try
{
using (var graphics = CreateGraphics())
{
foreach (var text in Lines)
{
var textArea = graphics.MeasureString(text, Font);
if (textArea.Width < Width)
linesHeight += textHeight;
else
{
var numLines = (float)Math.Ceiling(textArea.Width / Width);
linesHeight += textHeight * numLines;
}
}
}
if (linesHeight > Height)
ScrollBars = ScrollBars.Vertical;
else
ScrollBars = ScrollBars.None;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
finally
{
BorderStyle = borderStyle;
ResumeLayout();
}
}
private void OnResize(object sender, EventArgs e)
{
m_timerResize.Stop();
m_timerResize.Tick -= OnDelayedResize;
m_timerResize.Tick += OnDelayedResize;
m_timerResize.Interval = 475;
m_timerResize.Start();
}
Timer m_timerResize = new Timer();
private void OnDelayedResize(object sender, EventArgs e)
{
m_timerResize.Stop();
Resize -= OnResize;
AutoScrollVertically();
Resize += OnResize;
}
}