c++ - iconos - herramientas de word 2016
Dibujando manualmente degradados para botones, barras de herramientas, pestaƱas, etc. (3)
Me gustaría actualizar algún código similar a una barra de herramientas para tener una redondez de gradiente de Vista / Win7.
Actualmente, los botones tienen el aspecto y funcionamiento de Windows 2000: blocky, single-tone.
He jugado con los temas de XP y usando DrawThemeBackground, DrawThemeEdge, etc .; pero estoy muy insatisfecho con la mecánica del dibujo del tema (los botones son grandes, y el tema los dibuja como dos tonos, mitad superior e inferior, que se ve bien cuando los botones son pequeños; les da una apariencia medianamente decente de ser un gradiente o tener una calidad redondeada para ellos. Pero a pesar de lo grandes que son estos botones, se ven estúpidos.
Experimentando simplemente observando cuántos de los controles se dibujan en varias aplicaciones y controles, puedo ver que la mayoría de ellos parecen usar degradados, donde la parte superior del control aparece de color claro y se desvanece hasta el fondo a un color más oscuro - O - donde es un color más claro que el fondo en la parte superior, aumenta hacia casi blanco en el centro, luego se desvanece a un color más oscuro hacia la parte inferior.
No estoy seguro de a dónde ir desde aquí. DrawThemeXXX parece ser inadecuado. Realmente no quiero reemplazar todo el control con uno nuevo que haya mejorado el dibujo, pero requeriría que intercambie parte del código sobre cómo funciona el control personalizado actual y arriesgue varios problemas con alguna otra biblioteca. Prefiero tener una forma de dibujar objetos arbitrarios en el estilo de la versión actual de Windows en la que estoy ejecutando. Hubiera pensado que las funciones de dibujo del tema habrían cubierto esto. Pero están bastante dañados del cerebro, como describí.
¿Alguien puede apuntarme hacia ''¿Cómo se supone que las aplicaciones modernas de C ++ dibujan elementos de GUI personalizados para que razonablemente puedan esperar una apariencia elegante en XP, Vista y Windows 7?''
En este momento usamos MFC, Gdiplus y API Win32 sin formato.
¡Espero que alguien sepa mucho sobre cómo dibujar GUI modernas en Windows desde C ++!
Para que esto no sea una pared de texto, aquí está la versión actual del controlador de pintura, que dibuja el botón con un borde grabado cuando ''hot-tracking'' y tanto un borde grabado como el icono + texto "deprimido" (desplazado por 1,1) cuando está en estado comprimido:
void CPlacesButton::PaintButton(CDC & dc, CRect & rcClient)
{
const int kLabelHeight = 8;
COLORREF clrHiLt = GetSysColor(COLOR_BTNHIGHLIGHT);
COLORREF clrShdo = GetSysColor(COLOR_BTNSHADOW);
COLORREF clrText = GetSysColor(COLOR_BTNTEXT);
COLORREF clrFace = GetSysColor(COLOR_BTNFACE);
// draw the button''s background & border
if (m_bPressed || m_bDrawPressed || m_bMouseOnButton)
{
COLORREF clrDarkened = Darken(clrFace, -0.01f);
dc.FillRect(rcClient, &CBrush(clrDarkened));
//dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
//dc.RoundRect(&rcClient, CPoint(10,10));
dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT|BF_FLAT);
//dc.DrawFrameControl(&rcClient, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
}
// else if (m_bMouseOnButton) // hot draw
// //dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
// dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT);
// //dc.RoundRect(&rcClient, CPoint(10,10));
else
dc.FillRect(rcClient, &CBrush(clrFace));
// use transparent mode for everything that follows
dc.SetBkMode(TRANSPARENT);
// center icon
CPoint ptIcon((rcClient.Width() - m_nIconSize) / 2, ((rcClient.Height() - m_nIconSize) / 2) - kLabelHeight);
if (m_bPressed || m_bDrawPressed)
ptIcon.Offset(1, 1);
// determine the state to draw ourselves in
const UINT nState = DST_ICON | (IsEnabled() ? DSS_NORMAL : DSS_DISABLED);
// draw our icon
dc.DrawState(ptIcon, CSize(m_nIconSize, m_nIconSize), m_hIcon, nState, (HBRUSH)NULL);
// create & select the font to use for the button''s label
CFont guiFont;
VERIFY(guiFont.CreateStockObject(DEFAULT_GUI_FONT));
AutoSelectGDIObject select_font(dc, guiFont);
// determine clipping rect for label
CRect rcText(0, ptIcon.y+m_nIconSize+kLabelHeight, rcClient.Width(), ptIcon.y+m_nIconSize+kLabelHeight);
rcText.InflateRect(0,20);
if (m_bPressed || m_bDrawPressed)
rcText.OffsetRect(1, 1);
dc.SetTextColor(clrText);
if (IsEnabled())
dc.DrawText(m_strCaption, rcText, DT_VCENTER|DT_SINGLELINE|DT_CENTER);
else
dc.GrayString(NULL, NULL, (LPARAM)(LPCTSTR)m_strCaption, 0, rcText.TopLeft().x, rcText.TopLeft().y, rcText.Width(), rcText.Height());
}
Dejé algunas de las variaciones comentadas en el código para indicar algunas pistas sobre qué otras posibilidades he probado. Sin embargo, son solo una pista, ya que los ejemplos alternativos completos no están presentes.
En realidad, duplicar el aspecto de los diversos sabores de Windows es ridículamente difícil, especialmente si tu aplicación puede ejecutarse en más de una versión de Windows.
Creo que intentaron darte la API para hacer esto en los días de Win2k / Win95, pero luego WinXP apareció con sombreado y superposiciones, y la antigua API era completamente inadecuada.
Así que se les ocurrió el tema, que en realidad no es ni siquiera una API, sino una API y un conjunto de primitivas gráficas todas juntas. Pero no cumplieron y permitieron que el conjunto de primitivas gráficas se extendiera o reemplazara, por lo que los temas solo funcionan cuando los controles se asemejan mucho al conjunto estándar.
Entonces, para Win9x / Win2k. Tu usas
DrawFrameControl
DrawEdge
Para WinXP
DrawTheme
Para WinVista / 7
DrawTheme
DwmXXX functions
GradientFill ??
Ahora sospecho que Windows no está usando GradientDraw. Sospecho que en realidad está usando algunos sombreadores DX10 que están integrados en el código del administrador de ventanas, pero no sé cómo llegar a eso, s he estado usando GradientDraw en su lugar. Este código le dará un fundido lineal desde la parte superior del control hasta la parte inferior.
INLINE void SetTrivertex(TRIVERTEX & vtx, int x, int y, COLORREF cr)
{
vtx.x = x;
vtx.y = y;
vtx.Red = (SHORT)(GetRValue(cr) * 256L);
vtx.Green = (SHORT)(GetGValue(cr) * 256L);
vtx.Blue = (SHORT)(GetBValue(cr) * 256L);
vtx.Alpha = (SHORT)(255 * 256L);
}
...
// fill the interior from the top down with a gradient that starts at crTop
// and ends with the crBottom
TRIVERTEX vtx[2];
SetTrivertex (vtx[0], prc->left+1, prc->top+1, crTop);
SetTrivertex (vtx[1], prc->right-1, prc->bottom-1, crBottom);
GRADIENT_RECT gRect = { 0, 1 };
GradientFill(hdc, vtx, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
MFC solo no es exactamente amigable. Además de usar otra GUI ( Qt es ideal para skinning personalizado), puede buscar soluciones como SkinCrafter .
Nunca mencionaste el paquete de características de MFC. ¿Ya lo has echado un vistazo? Descargar para VS2008, incluido con VS2008 SP1. El CDrawingManager tiene muchos efectos especiales. Tiene un gran soporte para temas de aplicaciones.