Controlos de empilhamento (WinForms C #) (transparente)
-
22-07-2019 - |
Pergunta
Pediram-me para escrever um GUI que permitirá que objetos para ser empilhados dentro de um recipiente. O usuário estará vendo as caixas de uma parte superior para baixo ponto de vista. Eles também gostaria de ser capaz de ver o que está empilhada dentro. Meu primeiro pensamento para resolver este foi a transparência. Eu li alguns dos posts sobre a transparência, no entanto I não encontrou qualquer que resolveu as questões de ambas as imagens ser transparente para que você foi capaz de ver ambos se eles estão empilhados.
Como posso obter o controle para ser transparente com outros controles na parte superior. Se isso não é realmente possível; O que é uma melhor aproach para este problema?
Eu estou usando um controle personalizado (público classe MyControl parcial: Control) para resolver a questão. Eu finalmente ter a imagem no controle transparente. Tudo o que é desenhado no formulário pai mostra através da imagem (estou usando o OnPaint para o pai a pintar uma elipse e um quadrado), no entanto outros controles colocados sobre ele não é mais transparente.
O código que estou usando para alcançar este objetivo é abaixo:
public Image Image
{
get { return m_Image; }
set { m_Image = value; }
}
private void GridControl_Paint(object sender, PaintEventArgs e)
{
if (Image != null)
{
Graphics g = e.Graphics;
Bitmap bitMap = new Bitmap(Image);
//This is not working... the color array always comes back empty
//This is how I would rather making things transparent...
Color[] colorArray = bitMap.Palette.Entries;
if (colorArray.Length > 0)
{
ColorMap[] colorMap = new ColorMap[colorArray.Length];
for (int index = 0; index < colorArray.Length; index++)
{
colorMap[index] = new ColorMap();
colorMap[index].OldColor = colorArray[index];
colorMap[index].NewColor = Color.Transparent;
}
}
//Ok fine so the above is not working... let me force it.
//Get each pixel in the image and change the color.
else
{
for (int x = 0; x < bitMap.Width; x++)
{
for (int y = 0; y < bitMap.Height; y++)
{
Color pixelColor = bitMap.GetPixel(x, y);
Color newColor = Color.FromArgb(100, pixelColor);
bitMap.SetPixel(x, y, newColor);
}
}
}
bitMap.MakeTransparent();
g.DrawImage(bitMap, this.ClientRectangle);
}
}
Solução 2
Eu não tenho sido capaz de encontrar uma boa solução para este problema. A única maneira que eu encontrei para fazer isso é através de criar um controle personalizado e usando um monte de código personalizado (que eu ainda não têm totalmente funcional). Vou fechar esta discussão com o ser resposta:
É muito complicado responder neste fórum.
Outras dicas
Você está bloqueado em usar WinForms? Se você precisar de fazer muito moderadamente complicado coisas gráficos (como você descreve) e não pode redesenhar seu aplicativo para contornar o problema, você pode fazer o salto para WPF.
Tem sido um tempo desde que eu joguei no GDI + gráficos, então aqui está uma idéia (mas nenhum código;)):
fazer seus controles empilhados realmente precisa trabalhar? Se não, você pode copiar sua aparência para bitmaps, escondê-los, em seguida, usar os bitmaps em sua própria rotina de pintura. Quando um controle necessidades para trabalhar, você pode mostrá-lo.
A propósito, usando bitmap.GetPixel ou SetPixel é muito lento. Aqui está algum código antigo que eu tinha em torno de mentir que bitmaps de 32 bits manipulado (onde o azul, verde, vermelho e alfa são bytes):
BitmapData bmpData = bitmap.LockBits(pixelRect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
byte* bytes = (byte*)bmpData.Scan0;
for (int row = 0; row < pixelRect.Height; row++)
{
for (int col = 0; col < pixelRect.Width * 4; ) // * 4: 4 bytes per pixel
{
bytes[row * bmpData.Stride + col++] = blue;
bytes[row * bmpData.Stride + col++] = green;
bytes[row * bmpData.Stride + col++] = red;
bytes[row * bmpData.Stride + col++] = alpha;
}
}
}
// Unlock the bits.
bitmap.UnlockBits(bmpData);