Good all! Before that, I didn’t work with drawing at all. A pity) There is a form with opacity = 60%. When uploading, DropTaskPanel (hereinafter referred to as control), inherited from Panel, is dynamically added to the form. It has the same transparency by default. I coped with the necessary events, the control is added, everything works - well done. But! There is one unrealized feature. The default control should have a border of a certain color - let's say red. At events DragOver \ Enter = color changes to some other. It seems to be simple, but this very control should be rounded + so that it is usable in the future, the border drawing should be described inside the DropTaskPanel class. What is the problem? - set BorderStyle is not a problem. The problem is that 1. the rounded corners of the element have no border if I use CreateRoundRectRgn 2. I tried to draw a GraphicsPath stupidly - it didn't work out.

Tell me what I'm doing wrong. Below is a listing of DropTaskPanel without the above.

using System; 

using System.Drawing; using System.Windows.Forms; using CCLib.Properties; using MLib; using ContentAlignment = System.Drawing.ContentAlignment; using IDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;

namespace CCLib {public class DropTaskPanel: Panel {public event Action Dropped;

  private Label DragD { get; set; } private Label Or { get; set; } private LinkLabel Browse { get; set; } private PictureBox Icon { get; set; } public Color BorderColor { get; set; } = Color.Gray; public int Corner { get; set; } = 20; public DropTaskPanel() { InitializeComponent(); DragD.DragEnter += DragD_DragEnter; DragD.DragOver += DragD_DragOver; DragD.DragDrop += DragD_DragDrop; Or.DragEnter += Or_DragEnter; Or.DragOver += Or_DragOver; Or.DragDrop += Or_DragDrop; Browse.DragEnter += Browse_DragEnter; Browse.DragOver += Browse_DragOver; Browse.DragDrop += Browse_DragDrop; Icon.DragEnter += Icon_DragEnter; Icon.DragOver += Icon_DragOver; Icon.DragDrop += Icon_DragDrop; } ~DropTaskPanel() { Dispose(false); } private void InitializeComponent() { Width = 340; Height = 112; AllowDrop = true; ForeColor = Color.Lime; AllowDrop = true; BorderStyle = BorderStyle.FixedSingle; DragD = new Label { Location = new Point(100, 5), ForeColor = Color.Lime, AutoSize = true, TextAlign = ContentAlignment.MiddleCenter, AllowDrop = true }; Or = new Label { Location = new Point(90, 90), ForeColor = Color.Lime, AutoSize = true, TextAlign = ContentAlignment.MiddleCenter, AllowDrop = true }; //TODO location if English Browse = new LinkLabel { Location = new Point(115, 90), ForeColor = Color.Lime, LinkColor = Color.Lime, ActiveLinkColor = Color.Green, LinkBehavior = LinkBehavior.HoverUnderline, AutoSize = true, TextAlign = ContentAlignment.MiddleCenter, AllowDrop = true }; Icon = new PictureBox { Location = new Point(130, 25), BackgroundImageLayout = ImageLayout.Stretch, Width = 74, Height = 65, SizeMode = PictureBoxSizeMode.StretchImage, AllowDrop = true, Image = Resources.drop }; Controls.Add(DragD); Controls.Add(Or); Controls.Add(Browse); Controls.Add(Icon); } #region panel drag events protected override void OnDragOver(DragEventArgs e) { Icon.Image = Resources.drop2; e.Effect = DragDropEffects.Copy; Point p = Cursor.Position; Win32Point wp; wp.x = pX; wp.y = pY; IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper(); dropHelper.DragOver(ref wp, (int)e.Effect); } protected override void OnDragEnter(DragEventArgs e) { e.Effect = DragDropEffects.Copy; var p = Cursor.Position; Win32Point wp; wp.x = pX; wp.y = pY; var dropHelper = (IDropTargetHelper)new DragDropHelper(); dropHelper.DragEnter(Handle, e.Data as IDataObject, ref wp, (int)e.Effect); } protected override void OnDragLeave(EventArgs e) { Icon.Image = Resources.drop; IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper(); dropHelper.DragLeave(); } protected override void OnDragDrop(DragEventArgs e) { Dropped?.Invoke(e); } #endregion #region included controls drag events private void Icon_DragEnter(object sender, DragEventArgs e) => OnDragEnter(e); private void Icon_DragOver(object sender, DragEventArgs e) => OnDragOver(e); private void Icon_DragDrop(object sender, DragEventArgs e) => OnDragDrop(e); private void Browse_DragEnter(object sender, DragEventArgs e) => OnDragEnter(e); private void Browse_DragOver(object sender, DragEventArgs e) => OnDragOver(e); private void Browse_DragDrop(object sender, DragEventArgs e) => OnDragDrop(e); private void Or_DragEnter(object sender, DragEventArgs e) => OnDragEnter(e); private void Or_DragOver(object sender, DragEventArgs e) => OnDragOver(e); private void Or_DragDrop(object sender, DragEventArgs e) => OnDragDrop(e); private void DragD_DragEnter(object sender, DragEventArgs e) => OnDragEnter(e); private void DragD_DragOver(object sender, DragEventArgs e) => OnDragOver(e); private void DragD_DragDrop(object sender, DragEventArgs e) => OnDragDrop(e); #endregion public void SetLanguage(Language language) { if (language == Language.English) { Browse.Text = Resources.DropTaskPanel_SetLanguage_browse; Or.Text = Resources.DropTaskPanel_SetLanguage_or; DragD.Text = Resources.DropTaskPanel_SetLanguage_drag_files_here; } else { Browse.Text = Resources.DropTaskPanel_SetLanguage_Browse_rus; Or.Text = Resources.DropTaskPanel_SetLanguage_Or_rus; DragD.Text = Resources.DropTaskPanel_SetLanguage_DragHere_rus; } } } 

}

Not to take into account the flaw with the blinking of PictureBox - I can handle it, this is not a priority.

    1 answer 1

    Your task is solved both simply and difficult at the same time.

    1. First, the complexity: If you want to implement a control of arbitrary shape (even in the hole, even in the shape of a letter, if you pull out the vector glyphs from the fonts), then you have to take over the entire drawing of your control. Everything from the word at all: the frames and effects in the selection and everything else. Standard borders and styles cannot be used, since they are tightly tied to WinAPI and it is impossible to change their form, in any case I did not find any options to do this even through direct calls to the WinAPI functions. If you are not afraid of this fact proceed to the next step.

    2. Set the shape of the outer border of the control using GraphicsPath and put it in the Control.Region property. Everything. From this point on, the active area (the area that reacts to events), as well as the visible area (everything that is drawn) of your control is determined by the boundary we set. The shape of the border can be absolutely any.

    For verification, you can take controls with known behavior, for example, a button and play with the Control.Region property. Reception tested in practice, seemed to work without comment, if you find bugs, be sure to share =)

    • thanks, I will try and accomplish your goal - sky49rus
    • long did not come here. Thanks for the advice - everything turned out well, and I removed the pictureboxes and labels (not to blink and not to write extra code), replacing them with a drawing - sky49rus