Прозрачная форма C# с использованием элементов управления рисованием UpdateLayeredWindow
Я разрабатываю exe, где мне нужно иметь прозрачный фон. Я сделал изображение в Photoshop
и в нем есть все аккуратные вещи (тени / непрозрачность, отражение и т. д.).
Я изо всех сил пытался заставить это работать, используя TransparentColor + BackColor + Background Image, но я всегда заканчиваю с некоторым пикселем, не прозрачным. Таким образом, я переключился на UpdateLayeredWindow, который работает нормально, но никакой элемент управления не рисуется.
Вот часть моего кода
private void Form1_Load(object sender, EventArgs e)
{
UpdateFormDisplay(this.BackgroundImage);
}
protected override void OnPaint(PaintEventArgs e)
{
UpdateFormDisplay(this.BackgroundImage);
}
public void UpdateFormDisplay(Image backgroundImage)
{
IntPtr screenDc = API.GetDC(IntPtr.Zero);
IntPtr memDc = API.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try
{
//Display-image
Bitmap bmp = new Bitmap(backgroundImage);
hBitmap = bmp.GetHbitmap(Color.FromArgb(0)); //Set the fact that background is transparent
oldBitmap = API.SelectObject(memDc, hBitmap);
//Display-rectangle
Size size = bmp.Size;
Point pointSource = new Point(0, 0);
Point topPos = new Point(this.Left, this.Top);
//Set up blending options
API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
blend.BlendOp = API.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = API.AC_SRC_ALPHA;
API.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, API.ULW_ALPHA);
//Clean-up
bmp.Dispose();
API.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
API.SelectObject(memDc, oldBitmap);
API.DeleteObject(hBitmap);
}
API.DeleteDC(memDc);
}
catch (Exception)
{
}
}
Вот несколько изображений, чтобы объяснить лучше
1 ответ
Если вы хотите использовать регулярное управление внутри многоуровневого окна, которое использует UpdateLayeredWindow
API, вам нужно переопределить контроль OnPaint
метод для перенаправления рисунка в закадровый рисунок, который вы позже используете с UpdateLayeredWindow
способ обновить внешний вид окна.
Если вы не хотите копаться в коде элементов управления или не имеете много пользовательских элементов управления, WM_PRINT
сообщение может быть использовано, чтобы заставить элементы управления рисовать себя в предоставленном контексте устройства. Классическое оконное наследование (SetWindowLong
/GetWindowLong
) для ловли моментов, когда элементы управления аннулируют себя, полезно, но может быть немного опасно - вы должны следить за цепочкой обратных вызовов.
Наконец, вы можете использовать легкие (без окон) элементы управления. Они используют очередь сообщений формы для получения событий и отрисовки самих себя, поэтому необходимы только модификации кода отрисовки формы. Некоторые стандартные элементы управления winforms поддерживают этот режим.