Pergunta

Usando C # e .Net 2.0, estou usando uma forma irregular (TransparencyKey, FormBorderStyle = None, etc ...) e quer permitir o modo "normal" fronteira.

Eu mudar a cor de volta para o padrão de Lime Eu mudar FormBorderStyle para FixedSingle Eu mudar o TransparencyKey para Colour.None

Unfortuanately isso parece uma bagunça completa na tela com a imagem pulando alguns pixels para baixo e para o lado e Lime forma verde.

Eu acho que isso é causado pela forma sendo redesenhado depois de cada linha de código, é possível suspender o desenho do formulário até que eu fiz as minhas alterações e, em seguida, apenas redesenhar o formulário uma vez?

G

Foi útil?

Solução

NEW resposta:. Substituir o WndProc e bloquear a mensagem WM_PAINT enquanto você aplicar as novas propriedades da janela

velha resposta:. Substituir o WndProc, e bloquear a mensagem WM_ERASEBKGND

Explicação do que o código abaixo faz:

Quando a região de uma janela é invalidada, o Windows envia uma série de mensagens ao controle que resultam em um widget recém-pintada. Uma mensagem no início desta série é WM_ERASEBKGND. Normalmente, em resposta a esta mensagem, o controlo pinta-se um sólido cor. Mais tarde, em resposta à mensagem WM_PAINT (que normalmente é consumido por nós no evento OnPaint) o desenho real é feito. Se este desenho não é trivial, haverá um atraso antes que o widget é atualizado e você terá uma cintilação irritante.

Olhando para o código novamente eu estava resolvendo claramente um problema diferente. Experimente este novo exemplo. Ele irá bloquear a pintura do formulário / controle se o sinalizador bAllowPaint é desactivado.

O NEW exemplo:

    private const int WM_PAINT = 0x000F;

    protected override void WndProc(ref Message m)
    {
        if ((m.Msg != WM_PAINT) ||
            (bAllowPaint && m.Msg == WM_PAINT))
        {
            base.WndProc(ref m);
        }
    }

O OLD exemplo:

    private const int WM_ERASEBKGND = 0x0014;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg != WM_ERASEBKGND) // ignore WM_ERASEBKGND
        {
            base.WndProc(ref m);
        }
    }

Outras dicas

Tente a propriedade Form.DoubleBuffered. Configurá-lo para 'true'.

Além disso, se o seu formulário tem os controles filho, também definir DoubleBuffered a verdade para aqueles, bem como (e filhos de filhos, etc, para baixo da linha).

Por fim, chamada SuspendLayout antes de suas alterações e ResumeLayout depois. Tenha em mente isso só afeta colocação de controles filho. Se você estiver fazendo qualquer desenho personalizado a propriedade DoubleBuffered lhe dará mais para bater a bola.

Você está modificando as propriedades que têm uma bastante grande impacto em um formulário. TransparencyKey e FormBorderStyle exigem alteração dos bits de estilo janela. O Windows não permitir que esses bits de estilo a ser alterado. Windows Forms implementa-los, destruindo completamente a janela e re criando-lo a partir do zero. truque, mas isso leva tempo e forma será pintada novamente a cada vez que você muda o estilo. Fazendo com que o efeito visual desagradável que você vê.

Tente isto: 1. Definir opacidade para 0 para que o formulário se torna invisível 2. Mudança BackColor, não há problema 3. Mudança FormBorderStyle, a janela seja recriado 4. Altere TransparencyKey, a janela seja recriado 5. Alterar opacidade para 1, a janela seja recriado, em seguida, visível

Por exemplo:

  this.Opacity = 0;
  this.BackColor = Color.FromKnownColor(KnownColor.Control);
  this.FormBorderStyle = FormBorderStyle.Sizable;
  this.TransparencyKey = Color.Empty;
  this.Opacity = 1;

Se tudo isso falhar, você pode tentar alguns baixo nível de hackers bloqueando todas as mensagens de pintura ao seu formulário.

AVISO: Eu não estou promovendo o uso deste método, mas você pode experimentá-lo se você realmente quer. Ele me ajudou no passado.

Win32.LockWindowUpdate(this.Handle);
try
{
   //make your changes here
}
finally
{
  //release the lock
  Win32.LockWindowUpdate((IntPtr)0);
}

Este código baseia-se no código de suporte seguinte:

public class Win32
{
  private Win32() { }

    /// <summary>
    /// Lock ore relase the wndow for updating.
    /// </summary>
    [DllImport("user32")]
    public static extern int LockWindowUpdate(HWND hwnd);
 }

A maneira de enviar toda a "imagem" do formulário para a tela em uma única etapa é permitir DoubleBuffer.

No construtor você pode definir as ControlStyles

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top