Recentemente, num post que tratava sobre outro assunto, quando foi mensionado um exemplo que introduzia um novo botão na barra de título da janela, apareceram questionamentos sobre se ele utilizava ou não o tema do Windows.
Ficou a dúvida, a curiosidade. Seria fácil utilizar o recurso de tema do windows para desenhar um novo botão na barra de título? Bom, isto envolveria muito mais que simplesmente desenhar utilizando o tema. É necessário processar mensagens específicas (as Non Client - WM_NC...). Foi discutida também a se o botões padrões na barra de título(Max, Min, Restore, Close) seriam ou não bitmap's. E verificamos que no caso específico do uso de tema, tratam-se de bitmaps (veja figuras neste link)
Depois de trocar algumas MP's com o Thales, achei que poderia ser interessante trocar idéia sobre o assunto. Este questionamento não é urgente, mas acredito que possamos descobrir os detalhes mais rápidos se houver mais pessoas interessadas em investigar.
Aplicação para este conhecimento? Bom, acho que pensaremos em alguma. Na verdade, uma delas é a personalização de componentes, já que você pode construir componentes e desenhar eles utilizando as configurações de temas como você bem entender - desenhar o THeadControl utilizando a "textura" da barra de títulos, p.e..
- Partes e estados, os principais parâmetros que as funções utilizam -> Parts and States(P&S)
A partir da versão 7 do Delphi, foi incluida a unit UxTheme (delphipath\source\rtl\win), se alguém se interessar pelo assunto e não a possuir acredito que baste conseguir/solicitar para resolver esta questão.
Eu comecei meu programa teste com um form e um label, apenas para ter um retorno visual sobre o processo de inicialização do uso de tema:
procedure TForm1.FormCreate(Sender: TObject);
begin
if InitThemeLibrary then
begin
if UseThemes then
Label1.Caption := 'XP Theme inicializado e tema está em uso'
else
Label1.Caption := 'XP Theme inicializado e tema não está em uso';
end else
Label1.Caption := 'Não foi possível inicilizar recuros para uso de temas (XP Theme)';
end;
InitThemeLibrary retornará true apenas se conseguir carregar uxtheme.dll e inicializar o ponteiro para as funções nela presentes.
Introduzindo um botão e mais um label, tentei obter qual (dos 3) temas está em uso. Encontrei uma forma que foi através da localização das imagens. Utilizando a função GetThemeFilename é possível obter o nome e localização base da figura quando o parâmetro é TMT_IMAGEFILE (veja ref. P&S para especificar a imagem de 1 a 5):
procedure TForm1.Button1Click(Sender: TObject);
var
HndTheme :HTheme;
ThemeFileName,
ThemeClasseList :array[0..255] of WideChar;
ThemePart,
ThemeState :LongInt;
begin
StringToWideChar('WINDOW', ThemeClasseList, SizeOf(ThemeClasseList));
HndTheme := OpenThemeData(Handle, ThemeClasseList);
if HndTheme > 0 then
begin
ThemePart := WP_CLOSEBUTTON;
ThemeState := CBS_HOT; // CBS_DISABLED CBS_HOT CBS_NORMAL CBS_PUSHED
if GetThemeFilename(HndTheme, ThemePart, ThemeState, TMT_IMAGEFILE, ThemeFileName, SizeOf(ThemeFileName)) = S_OK then
begin
Label2.Caption := 'GetThemeFilename retornou: '+WideCharToString(ThemeFileName);
end else
Label2.Caption := 'Houve erro ao executar GetThemeFilename';
CloseThemeData(hndTheme);
end else
ShowMessage('Não foi possível encontrar a classe '+WideCharToString(ThemeClasseList));
end;
Observar a necessidade de os parâmetros "strings" serem utilizados no formato WideChar.
A alteração do tema em meu Desktop seguida da execução do programa resutou no seguinte:
1) Metallic\CloseButton.bmp
2) Blue\CloseButton.bmp
3) HomeStead\CloseButton.bmp
Isto já confirma que os botões da barra de título são realmente bitmap's.
Desabilitar o uso de tema (Estilo tema clássico do Windows), resultou em:
- no Label1 -> XP theme inicializado e não está em uso;
- no Label2 -> nada escrito e apresentada mensagem Não foi possível encontrar a classe WINDOW.
Desenhando o botão na área de cliente da janela principal (apenas a parte alterada):
...
end else
Label2.Caption := 'Houve erro ao executar GetThemeFilename';
DrawThemeBackground(HndTheme, Canvas.Handle, ThemePart, ThemeState, Rect(150, 32, 150 +25, 32 +25), nil);
CloseThemeData(hndTheme);
end else
...
Observar que a localização é em relação a área de cliente de cujo o HDC é passado.
Assim, se introduzirmos um Panel no form, poderemos desenhar a mesma imagem dentro dele, porém, neste caso, como não temos acesso ao canvas do TPanel, teremos que criar um Device Context (DC) para ele (apenas a parte alterada):
procedure TForm1.Button1Click(Sender: TObject);
var
DC :HDC;
HndTheme :HTheme;
...
end else
Label2.Caption := 'Houve erro ao executar GetThemeFilename';
DrawThemeBackground(HndTheme, Canvas.Handle, ThemePart, ThemeState, Rect(150, 32, 150 +25, 32 +25), nil);
DC := GetDC(Panel1.Handle);
DrawThemeBackground(HndTheme, DC, ThemePart, ThemeState, Panel1.ClientRect, nil);
ReleaseDC(Panel1.Handle, DC);
CloseThemeData(hndTheme);
end else
...
Acho que ficou meio com cara de tutorial, mas queria já adiantar um pouco do que descobri (quase nada).
Algumas dúvidas:
1) DrawThemeIcon é uma função que parece ser de grande utilidade. Entretanto, tentei adicionar um TImageList e passar seu handle para esta função e não obtive sucesso. Se alguém conseguir fazer uso dela com o componente TImagelist, por favor post aqui.
2) Não consegui, ainda, entender para que serve ou por que utilizar a passagem de mais de uma classe no parâmetro ThemeClasseList em OpenThemaData. Alguma ideia?
3) Será que é possível utilizar/carregar um tema para minha aplicação que não seja o que atualmente está definido no Windows XP?
Pergunta
Micheus
Recentemente, num post que tratava sobre outro assunto, quando foi mensionado um exemplo que introduzia um novo botão na barra de título da janela, apareceram questionamentos sobre se ele utilizava ou não o tema do Windows.
Ficou a dúvida, a curiosidade. Seria fácil utilizar o recurso de tema do windows para desenhar um novo botão na barra de título? Bom, isto envolveria muito mais que simplesmente desenhar utilizando o tema. É necessário processar mensagens específicas (as Non Client - WM_NC...). Foi discutida também a se o botões padrões na barra de título(Max, Min, Restore, Close) seriam ou não bitmap's. E verificamos que no caso específico do uso de tema, tratam-se de bitmaps (veja figuras neste link)
Depois de trocar algumas MP's com o Thales, achei que poderia ser interessante trocar idéia sobre o assunto. Este questionamento não é urgente, mas acredito que possamos descobrir os detalhes mais rápidos se houver mais pessoas interessadas em investigar.
Aplicação para este conhecimento? Bom, acho que pensaremos em alguma. Na verdade, uma delas é a personalização de componentes, já que você pode construir componentes e desenhar eles utilizando as configurações de temas como você bem entender - desenhar o THeadControl utilizando a "textura" da barra de títulos, p.e..
Referências msdn:
- Tudo sobre as funções/estruturas/... relacionadas a tema -> Visual Style Reference
- Partes e estados, os principais parâmetros que as funções utilizam -> Parts and States(P&S)
A partir da versão 7 do Delphi, foi incluida a unit UxTheme (delphipath\source\rtl\win), se alguém se interessar pelo assunto e não a possuir acredito que baste conseguir/solicitar para resolver esta questão.
Eu comecei meu programa teste com um form e um label, apenas para ter um retorno visual sobre o processo de inicialização do uso de tema:
InitThemeLibrary retornará true apenas se conseguir carregar uxtheme.dll e inicializar o ponteiro para as funções nela presentes. Introduzindo um botão e mais um label, tentei obter qual (dos 3) temas está em uso. Encontrei uma forma que foi através da localização das imagens. Utilizando a função GetThemeFilename é possível obter o nome e localização base da figura quando o parâmetro é TMT_IMAGEFILE (veja ref. P&S para especificar a imagem de 1 a 5): Observar a necessidade de os parâmetros "strings" serem utilizados no formato WideChar. A alteração do tema em meu Desktop seguida da execução do programa resutou no seguinte: 1) Metallic\CloseButton.bmp 2) Blue\CloseButton.bmp 3) HomeStead\CloseButton.bmp Isto já confirma que os botões da barra de título são realmente bitmap's. Desabilitar o uso de tema (Estilo tema clássico do Windows), resultou em: - no Label1 -> XP theme inicializado e não está em uso; - no Label2 -> nada escrito e apresentada mensagem Não foi possível encontrar a classe WINDOW. Desenhando o botão na área de cliente da janela principal (apenas a parte alterada): Observar que a localização é em relação a área de cliente de cujo o HDC é passado. Assim, se introduzirmos um Panel no form, poderemos desenhar a mesma imagem dentro dele, porém, neste caso, como não temos acesso ao canvas do TPanel, teremos que criar um Device Context (DC) para ele (apenas a parte alterada):Acho que ficou meio com cara de tutorial, mas queria já adiantar um pouco do que descobri (quase nada).
Algumas dúvidas:
1) DrawThemeIcon é uma função que parece ser de grande utilidade. Entretanto, tentei adicionar um TImageList e passar seu handle para esta função e não obtive sucesso. Se alguém conseguir fazer uso dela com o componente TImagelist, por favor post aqui.
2) Não consegui, ainda, entender para que serve ou por que utilizar a passagem de mais de uma classe no parâmetro ThemeClasseList em OpenThemaData. Alguma ideia?
3) Será que é possível utilizar/carregar um tema para minha aplicação que não seja o que atualmente está definido no Windows XP?
[]s
p.s. andei dando uma mexida no texto
Link para o comentário
Compartilhar em outros sites
1 resposta a esta questão
Posts Recomendados
Participe da discussão
Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.