I'm attempting to use code I've found that uses Win32. However, I'm getting this error:
The Name 'Win32' does not exist in the current context.
What am I missing? How do you call/declare Win32?
public class TransparentTextBox : TextBox
{
PictureBox pictureBox = new PictureBox();
public TransparentTextBox()
{
pictureBox.Dock = DockStyle.Fill;
this.Controls.Add(pictureBox);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case Win32.WM_PAINT:
Bitmap bmpCaptured =
new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
Bitmap bmpResult =
new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
Rectangle r =
new Rectangle(0, 0, this.ClientRectangle.Width,
this.ClientRectangle.Height);
CaptureWindow(this, ref bmpCaptured);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
ImageAttributes imgAttrib = new ImageAttributes();
ColorMap[] colorMap = new ColorMap[1];
colorMap[0] = new ColorMap();
colorMap[0].OldColor = Color.White;
colorMap[0].NewColor = Color.Transparent;
imgAttrib.SetRemapTable(colorMap);
Graphics g = Graphics.FromImage(bmpResult);
g.DrawImage(bmpCaptured, r, 0, 0, this.ClientRectangle.Width,
this.ClientRectangle.Height, GraphicsUnit.Pixel, imgAttrib);
g.Dispose();
pictureBox.Image = (Image)bmpResult.Clone();
break;
case Win32.WM_HSCROLL:
case Win32.WM_VSCROLL:
this.Invalidate(); // repaint
// if you use scrolling then add these two case statements
break;
}
}
Those are not defined in the .NET framework. Whoever wrote this code had them defined in another class. They are from the Win32 API which is why they are named Win32. You'll need to search on each of those defines and find out what they should be.
I can tell you that the Win32.WH* are window messages they are just integer values.
Edit: pinvoke.net has a full list of window messages.
I suspect you have grabbed code that relies on this Win32 helper class.
Adding that to your project should solve the immediate Win32 missing problem.
Yeah, do what David said which you said you already did (pInvoke). Then look at the source you found and look where Win32.WM_PAINT, Win32.WM_HSCROLL, and Win32.WM_VSCROLL are defined. In my experience, these are just defined by hand in the source and are just numbers, to make it easier to read. Of course these numbers correspond to what they're actually defined in the Win32 API, but they're redefined in the source by the programmer to avoid having to use the numbers directly, therefore making it harder to read.
On the other hand, if you want a transparent textbox, why not just reference PresentationCore/PresentationFramework/WindowsFormsIntegration and use this to create a transparent text box:
using WPFTextBox = System.Windows.Controls.TextBox;
using WPFBrushes = System.Windows.Media.Brushes;
using WPFElementHost = System.Windows.Forms.Integration;
...
var textBox = new WPFTextBox { Background = WPFBrushes.Transparent };
var host = new WPFElementHost { Dock = DockStyle.Fill, Child = textBox };
then add the host to your container and you're set to go. A lot easier than messing with a bunch of Win32 complexity, and easy to wrap in a custom class.
Why beat your head against WinForms when the functionality is trivial to achieve in WPF? Windows 98, ME, and 2000 now account for about 1% of the market in total. (WPF won't run on any Windows OS below XP)
Related
I couldnt find anything like that at all (basicly every problem from so else is always a syntax problem) and well..., the situation is a bit more complicated. to avoid using 500 lines of code im going to describe it for the most part:
Ive got a Form wich is acting as a parent Form (MdiParent) and another Form wich is a Child but basicly a fully functional Form at its own. Im using several OnPaint methods in the childform, witch work perfectly fine, and 3 custom buttons on the parent Form witch also have their own OnPaint methods. These 3 buttons (actualy panels) and every other control on the parent Form are contained in a PictureBox witch fills the parent Form completely and is used to make the background of the parent transparent / clickthrough via TransparencyKey (havnt found any other ways of doing that).
the Problem is that every OnPaint Method on the parent wont work at all (they're beeing executed but dont paint anything).
here is some code but that isnt the problem i'd say:
this.myButtonObject1.BackColor = System.Drawing.Color.Red;
this.myButtonObject1.Location = new System.Drawing.Point(840, 0);
this.myButtonObject1.Name = "myButtonObject1";
this.myButtonObject1.Size = new System.Drawing.Size(50, 50);
this.myButtonObject1.TabIndex = 0;
this.myButtonObject1.Click += new System.EventHandler(this.myButton1_Click);
this.myButtonObject1.Paint += new System.Windows.Forms.PaintEventHandler(this.myButtonObject1_Paint);
private void myButtonObject1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
LinearGradientBrush lgb = new LinearGradientBrush(new PointF(0, 0), new PointF(myButtonObject1.Width, myButtonObject1.Height), Color.Green, Color.Lime);
Pen p = new Pen(lgb, 5);
g.DrawRectangle(p, myButtonObject1.Bounds);
lgb.Dispose();
p.Dispose();
}
if anyone can tell me; what am i doing wrong?
PS: i m using .net 4.5, VS 2015, and havnt changed any of the default settings besides TopMost FormBorderStyle ShowInTaskbar StartPosition and ofc the color and trancparencyKey, but i dont think it has anything todo with that.
Update
The small error in your code is to use the Panel's Bounds property, which at runtime will refer to the Panel's Location within its Parent! But the drawing code must be relative to the object, not its parent!
So do not use Bounds but ClientRectangle and make sure to set the right PenAlignment:
using (LinearGradientBrush lgb =
new LinearGradientBrush(ClientRectangle, Color.Green, Color.Lime, 0f) ) //or some angle!
using (Pen p = new Pen(lgb, 5))
{
p.Alignment = PenAlignment.Inset;
g.DrawRectangle(p, ClientRectangle);
}
Set myButtonObject1.FlatStyle to FlatStyle.Standard.
I'm creating a view for patch files using AvalonEdit, and I want to make it so that diffs are highlighted across the entire line, not just the text background - similar to what GitHub for Windows does today:
I'm new to AvalonEdit, so I'm not sure the best way to do this. Here's what I've found so far:
Override VisualLineElementGenerator in order to create an additional TextSpan that is the length of the control. This seems Tricky.
Create a new control to add to TextView.Layers in the background and OnRender in the green/red by hand - this seems more promising, but it's not super clear what event I need to hook in order to detect when to re-render.
Override TextView - this seems like overkill.
Edit: Here's what happens with a simple syntax highlighter, which is what I don't want:
As Daniel mentioned, I discovered Background Renderers via the Wiki page and it worked great. Here's what I ended up doing - it can probably be made a bit more efficient but it's good enough for now:
public class DiffLineBackgroundRenderer : IBackgroundRenderer
{
static Pen pen;
static SolidColorBrush removedBackground;
static SolidColorBrush addedBackground;
static SolidColorBrush headerBackground;
FileDiffView host;
static DiffLineBackgroundRenderer()
{
removedBackground = new SolidColorBrush(Color.FromRgb(0xff, 0xdd, 0xdd)); removedBackground.Freeze();
addedBackground = new SolidColorBrush(Color.FromRgb(0xdd, 0xff, 0xdd)); addedBackground.Freeze();
headerBackground = new SolidColorBrush(Color.FromRgb(0xf8, 0xf8, 0xff)); headerBackground.Freeze();
var blackBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0)); blackBrush.Freeze();
pen = new Pen(blackBrush, 0.0);
}
public DiffLineBackgroundRenderer(FileDiffView host)
{
this.host = host;
}
public KnownLayer Layer
{
get { return KnownLayer.Background; }
}
public void Draw(TextView textView, DrawingContext drawingContext)
{
foreach (var v in textView.VisualLines)
{
var rc = BackgroundGeometryBuilder.GetRectsFromVisualSegment(textView, v, 0, 1000).First();
// NB: This lookup to fetch the doc line number isn't great, we could
// probably do it once then just increment.
var linenum = v.FirstDocumentLine.LineNumber - 1;
if (linenum >= host.ViewModel.Lines.Count) continue;
var diffLine = host.ViewModel.Lines[linenum];
if (diffLine.Style == DiffLineStyle.Context) continue;
var brush = default(Brush);
switch (diffLine.Style)
{
case DiffLineStyle.Header:
brush = headerBackground;
break;
case DiffLineStyle.Added:
brush = addedBackground;
break;
case DiffLineStyle.Deleted:
brush = removedBackground;
break;
}
drawingContext.DrawRectangle(brush, pen,
new Rect(0, rc.Top, textView.ActualWidth, rc.Height));
}
}
}
Create a new control to add to TextView.Layers in the background and OnRender in the green/red by hand
You don't have to create a new layer to render in something in the background: you can add your implementation of IBackgroundRenderer to textView.BackgroundRenderers to render something in the background of an existing layer.
it's not super clear what event I need to hook in order to detect when to re-render
That would be: textView.VisualLinesChanged. But you don't need that if you use IBackgroundRenderer as the existing layers are already re-rendered by AvalonEdit.
This SHOULD be a very simple question but after lots of searching there seems to be no working example anywhere.
I just want my XNA window to start off maximized.
I know how to set the width and height of the window, but that's not quite the same.
I also need to do this without going full screen. I just want a normal maximized window.
Set the IsFullScreen property of the graphics device manager to true.
http://msdn.microsoft.com/en-us/library/bb195024(v=xnagamestudio.10).aspx
//from the above msdn sample
graphics = new GraphicsDeviceManager( this );
content = new ContentManager( Services );
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.PreferMultiSampling = false;
graphics.IsFullScreen = true;
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphicsdevicemanager.isfullscreen(v=xnagamestudio.10).aspx
#Cyral has the closest answer so far, but it's still not quite what you want. To maximize a Windows Form, you use the WindowState property:
var form = (Form)Form.FromHandle(Window.Handle);
form.WindowState = FormWindowState.Maximized;
You can add a reference to System.Windows.Forms and System.Drawing (However, You will need to type the namespaces out, Because of ambiguities)
Use the following code after base.Initialize
Form form = (Form)Form.FromHandle(Window.Handle);
form.Location = Point(0, 0);
form.Size = Screen.PrimaryScreen.WorkingArea.Size;
Others have covered the step of maximizing automatically, but to enable the actual maximize button so the user can do it when desired, do this in the Game constructor:
Window.AllowUserResizing = true;
Depending on how you want the game to behave when resizing begins and ends, perhaps pause the game, you may need to handle some of these events.
Form form = (Form)Form.FromHandle(Window.Handle);
form.ResizeBegin += new EventHandler(form_ResizeBegin);
form.ResizeEnd += new EventHandler(form_ResizeEnd);
form.LocationChanged += new EventHandler(form_LocationChanged);
_graphics = new GraphicsDeviceManager(this);
DisplayMode displayMode = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode;
this._graphics.PreferredBackBufferFormat = displayMode.Format;
this._graphics.PreferredBackBufferWidth = (int)(displayMode.Width);
this._graphics.PreferredBackBufferHeight = (int)(displayMode.Height);
Sort of works for me but not quite, you'll understand once you try. I mean, it's not perfect and I'm sure there's a better way but for prototyping this should work - or maybe with some tweaking you could get what you need.
I'm using C#2.0 and I want to create a facebook style tooltip window. I currently made it with 2 windows and transparent key. One for the triangle arrow pointer and one for the square. The whole picture looks like that:
I have problem with the redrawing (as shown in the picture).
Is there a way to use whole shaped window on that? (While I need to make it sizeable)
If no, is this the proper way to make that? Or I need to 'glue' the triangle to the rectangle
Two ways to solve --
Using transparency: Irregular shaped Windows Form (C#)
Or using Control.Region which is the actual shaping of the window. Plenty of samples or:
How do I make a genuinely transparent Control?
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
const int ArrowSize = 25;
Point[] points = new[] {
new Point(ArrowSize, 0),
new Point(this.Width, 0),
new Point(this.Width, this.Height),
new Point(ArrowSize, this.Height),
new Point(ArrowSize, ArrowSize),
new Point(0, ArrowSize/2)
// don't need - autocloses
// ,new Point(ArrowSize, 0)
};
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
this.Region = new Region(path);
}
I have panel that I have customized. I use it to display text. But sometimes that text is too long and wraps to the next line. Is there some way I can auto resize the panel to show all the text?
I am using C# and Visual Studio 2008 and the compact framework.
Here is the code I am wanting to adjust the size for:
(Note: HintBox is my own class that inherits from panel. So I can modify it as needed.)
public void DataItemClicked(ShipmentData shipmentData)
{
// Setup the HintBox
if (_dataItemHintBox == null)
_dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(),
_dataShipSelectedPoint,
new Size(135, 50), shipmentData.LongDesc,
Color.LightSteelBlue);
_dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100,
_dataShipSelectedPoint.Y - 50);
_dataItemHintBox.MessageText = shipmentData.LongDesc;
// It would be nice to set the size right here
_dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString()
_dataItemHintBox.Show();
}
I am going to give the answer to Will Marcouiller because his code example was the closest to what I needed (and looks like it will work). However, this is what I think I will use:
public static class CFMeasureString
{
private struct Rect
{
public readonly int Left, Top, Right, Bottom;
public Rect(Rectangle r)
{
this.Left = r.Left;
this.Top = r.Top;
this.Bottom = r.Bottom;
this.Right = r.Right;
}
}
[DllImport("coredll.dll")]
static extern int DrawText(IntPtr hdc, string lpStr, int nCount,
ref Rect lpRect, int wFormat);
private const int DT_CALCRECT = 0x00000400;
private const int DT_WORDBREAK = 0x00000010;
private const int DT_EDITCONTROL = 0x00002000;
static public Size MeasureString(this Graphics gr, string text, Rectangle rect,
bool textboxControl)
{
Rect bounds = new Rect(rect);
IntPtr hdc = gr.GetHdc();
int flags = DT_CALCRECT | DT_WORDBREAK;
if (textboxControl) flags |= DT_EDITCONTROL;
DrawText(hdc, text, text.Length, ref bounds, flags);
gr.ReleaseHdc(hdc);
return new Size(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top +
(textboxControl ? 6 : 0));
}
}
This uses the os level call to draw text. By P-Invoking it I can get the functionality I need (multi line wrapping). Note that this method does not include any margins. Just the actual space taken up by the text.
I did not write this code. I got it from http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html. That blog post had my exact problem and this fix. (Though I did make a minor tweak to make it a extension method.)
You could use the Graphics.MeasureString() method.
With a code sample of your text assignment onto your panel, I could perhaps provide a code sample using the MeasureString() method, if you need it.
I have no way to know whether the Graphics.MeasureString() method is part of the Compact Framework, as it is not said on the page I linked.
EDIT #1
Here's a link where I answered to another text-size related question, while I look for writing a sample for you. =)
EDIT #2
Here's another link related to your question. (Next edit is the sample code. =P)
EDIT #3
public void DataItemClicked(ShipmentData shipmentData) {
// Setup the HintBox
if (_dataItemHintBox == null)
_dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(),
_dataShipSelectedPoint,
new Size(135, 50), shipmentData.LongDesc,
Color.LightSteelBlue);
// Beginning to measure the size of the string shipmentData.LongDesc here.
// Assuming that the initial font size should be 30pt.
Single fontSize = 30.0F;
Font f = new Font("fontFamily", fontSize, FontStyle.Regular);
// The Panel.CreateGraphics method provides the instance of Graphics object
// that shall be used to compare the string size against.
using (Graphics g = _dataItemHintBox.CreateGraphics()) {
while (g.MeasureString(shipmentData.LongDesc, f).Width > _dataItemHintBox.Size.Width - 5) {
--fontSize;
f = new Font("fontFamily", fontSize, FontStyle.Regular);
}
}
// Font property inherited from Panel control.
_dataItemHintBox.Font = f;
// End of font resizing to fit the HintBox panel.
_dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100,
_dataShipSelectedPoint.Y - 50);
_dataItemHintBox.MessageText = shipmentData.LongDesc;
// It would be nice to set the size right here
_dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString()
_dataItemHintBox.Show();
}
Disclaimer: This code has not been tested and is off the top of my head. Some changes might be obligatory in order for you to test it. This provides a guideline to achieve what you seem to want to accomplish. There might be a better way to do this, but I know this one works. Well, the algorithm works, as you can see in my other answers.
Instead of the line:
SizeF fontSize = 30.0F;
You could as well do the following:
var fontSize = _dataItemHintBox.Font.Size;
Why is this?
Because Font.Size property is readonly. So, you need to create a new instance of the System.Drawing.Font class each time the Font.Size shall change.
In your comparison, instead of having the line:
while (g.MeasureString(shipmentData.LongDesc, f)...)
you could also have:
while (g.MeasureString(shipmentData.LongDesc, _dataItemHintBox.Font)...)
This would nullify the need for a second Font class instance, that is f.
Please feel free to post feedbacks as I could change my sample to fit your reality upon the feedbacks received, so that it better helps you. =)
I hope this helps! =)
You can use whichever of the TextRenderer.MeasureText overloads is appropriate for you. Using this function, you can determine the actual rendered size of a string and adjust your panel's size accordingly.
If you're trying to measure inside the Paint event, then you could use the MeasureString function on your e.Graphics object, but resizing inside Paint is not wise. Using TextRenderer avoids your having to create a Graphics object with CreateGraphics() and disposing of it when you're finished.
EDIT
Since TextRenderer is not supported on the compact framework (I missed the tag the first time I saw the question), you'll have to use MeasureString() function on the Graphics object. Something like this:
public Size GetStringSize(string text)
{
using(Graphics g = yourPanel.CreateGraphics())
{
return g.MeasureString(text, yourPanel.Font);
}
}