Win32: Como fazer com que a Drop Shadow honra a janela em camadas não retangulares?
-
19-09-2019 - |
Pergunta
Eu criei um janela em camadas adicionando o Ws_ex_layered Estilo estendido:
wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;
O Windows usará o preto como o valor da cor da chave do Chroma. Vou deixar uma grande fronteira de preto para tornar o problema óbvio:
Depois que a janela é construída, eu digo para Use preto como uma cor de tecla croma:
SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);
Agora a janela pop -up em camadas parece parcialmente transparente:
O problema é a etapa final. Eu quero usar Cs_dropshadow Estilo de classe, disponível desde o Windows XP, para criar uma sombra de queda:
wndClass.Style = wndClass.Style | CS_DROPSHADOW;
A sombra aparece, mas a sombra circunda a janela retangular original e não leva em consideração a transparência da janela fornecida pela janela em camadas:
Alguém sabe que opção mágica perdi em algum lugar que fará com que a Drop Shadow honre a janela não retangular em camadas?
Outro exemplo de onde esse problema aparece é quando você não inclui o preenchimento/margem de 6px. A janela de sugestão, como desenhada por temas Windows®, não é retangular. Isso deixa uma pequena lacuna visível onde a janela é transparente, mas a sombra de gota não aparece:
A Microsoft conseguiu fazê -lo funcionar, como você pode ver nesta dica do Internet Explorer:
Olhando mais de perto em uma janela tooltips
Janela de dica de classe. Usando Spyxx - Eu posso obter a janela recret e os estilos de classe:
Spyxx diz:
Rectangle: (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect: (0, 0)-(104, 20), 104x20
Então, tudo aponta para a janela sendo 104x20 pixels, com a sombra de queda do lado de fora da janela. (Que é consistente com CS_DROPSHADOW
.)
Em seguida, posso olhar para os estilos do tooltips
Classe de janela:
Windows Styles: 94000001
WS_POPUP 80000000
WS_VISIBLE 10000000
WS_CLIPSIBLINGS 4000000
TTS_ALWAYSTIP 1
Extended Styles: 00080088
WS_EX_LAYERED 80000
WS_EX_TOOLWIN 80
WS_EX_TOPMOST 8
Curiosamente, não usa CS_SAVEBITS
(0x800
); o que é útil para janelas de pequena vida curta.
Nem usa CS_DROPSHADOW
(0x20000
). Então agora eu me pergunto como está desenhando fora de sua própria janela?
Observação: As janelas em camadas transparentes são documentadas como a técnica preferida sobre as regiões.
Editar: As janelas em camadas existem com o Windows 2000. CS_DROPSHADOW foi adicionado ao XP.
Solução
As janelas em camadas transparentes são documentadas como a técnica preferida sobre as regiões.
No entanto, CS_DROPSHADOW
faz Preste atenção às regiões. Se você cortar ou moldar sua janela usando uma região, a sombra de queda seguirá o novo esboço.
Felizmente, você posso Use regiões com janelas em camadas e, ao combinar os dois, obtenha o efeito que você está procurando.
BTW: ToolTips_class32 faz Use cs_dropshadow - você não o verá nos estilos de janela porque é um estilo de classe, não um estilo de janela.
Outras dicas
Por que você não usa lwa_alpha e construa a sombra na imagem?
Edite em resposta ao seu comentário:
A) Não impede você usar um PNG canalizado alfa apenas para uma sombra. BLT as 2 imagens juntas e use como uma única imagem.
B) Não é difícil gerar uma sombra. Na imagem, você postou seu preto com 3 valores alfa diferentes.
C) Mas não funciona? ou seja, é hora de ser criativo.
D) Em seguida, não tente fazer com que o Windows faça algo que não fará por você.
E) é totalmente irrelevante. As janelas em camadas lidam com isso para você.
Eu recomendo fortemente que você aprenda mais sobre janelas em camadas, porque elas podem ajudá -lo a seu objetivo.
Edit2: você tem o bitmap. É bastante fácil escanear a imagem e descobrir quais bits serão digitados em cores (identificando o negro) e quando modificará que ter um alfa de 0 onde tudo o mais terá um alfa de 255 (não: você pode ter que se converter A imagem para uma imagem de 32 bits a partir de um formato de cor inferior, você pode fazer isso criando um novo DC e copiando a imagem). Isso lhe dará o mesmo efeito com o LWA_ALPHA e LWA_COLORKEY. A partir daí, é bastante fácil identificar o pixel na borda, onde a cor muda para (r = 0, g = 0, b = 0, a = 0). Você então muda esse primeiro pixel para ter um alfa de 192, o que o sopra para 128 e o abaixo para 64. Agora você tem uma gradação alfa abaixo da imagem que se parecerá com a sombra. Você pode ajustar o alfa para obter o efeito desejado.
CS_DROPSHADOW
Funciona apenas com janelas retangulares padrão. WS_EX_LAYERED
As janelas não suportam tudo. Eles são mais um método de autoatendimento de baixo nível para desenhar exatamente o que você deseja.
Para obter uma sombra, você terá que gerar a sombra de queda do canal alfa na imagem.