Re: Paint on a Tabcontrol
What exactly does not work?
About Owner-Drawn Tabs you could read in MSDN
Re: Paint on a Tabcontrol
Thanks for the guidance.
So as I understand I have to use WM_DRAWITEM and not WM_PAINT.
I set up a DRAWITEMSTRUCT structure and try to paint in WM_DRAWITEM but it still won't work.
Code:
#include <windows.h>
#include <commctrl.h>
#include <iostream>
using namespace std;
#pragma comment(linker, "/subsystem:\"console\" /entry:\"WinMainCRTStartup\"")
#include <gdiplus.h>
using namespace Gdiplus;
#define ID_TAB 113
VOID OnPaint(HDC hdc)
{
Graphics graphics(hdc);
Pen pen(Color(255, 0, 0, 255));
graphics.DrawLine(&pen, 20, 20, 150, 550);
}
char className[]="TabControl";
HWND hTab;
HINSTANCE hInst;
// The struct that WM_DRAWITEM needs:
static DRAWITEMSTRUCT * it;
LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil)
{
MSG messages;
WNDCLASSEX wincl;
hInst = hInstance;
wincl.hInstance=hInstance;
wincl.lpszClassName=className;
wincl.lpfnWndProc=WindowProcedure;
wincl.style=0;
wincl.cbSize=sizeof(WNDCLASSEX);
wincl.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wincl.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
wincl.hCursor=LoadCursor(NULL,IDC_ARROW);
wincl.lpszMenuName=NULL;
wincl.cbClsExtra=0;
wincl.cbWndExtra=0;
wincl.hbrBackground=HBRUSH(COLOR_3DFACE+1);
if(!RegisterClassEx(&wincl))return 0;
HWND windowHandle=CreateWindow(className,"TabControl",
WS_OVERLAPPEDWINDOW,
200,325,480,320,
NULL,NULL,hInstance,NULL);
ShowWindow(windowHandle,SW_SHOW);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
};
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(message)
{
case WM_CREATE:
INITCOMMONCONTROLSEX icce;
icce.dwSize=sizeof(INITCOMMONCONTROLSEX);
icce.dwICC=ICC_TAB_CLASSES;
InitCommonControlsEx(&icce);
hTab=CreateWindow(WC_TABCONTROL,"",
WS_CHILD|WS_VISIBLE|TCS_OWNERDRAWFIXED,
6,0,474,320,
hwnd,
(HMENU)ID_TAB,hInst,NULL);
TCITEM tab1Data;
tab1Data.mask=TCIF_TEXT;
tab1Data.pszText="Tab1";
TabCtrl_InsertItem(hTab,0,&tab1Data);
// DRAWITEMSTRUCT
ZeroMemory(&it, sizeof(DRAWITEMSTRUCT));
it->CtlType = ODT_TAB;
it->CtlID = ID_TAB;
it->itemID = 0; // Item to be drawn
it->itemAction = ODA_FOCUS|ODA_DRAWENTIRE;
it->itemState = ODS_FOCUS; // More flags > look at MSDN
it->hwndItem = hTab; //GetDlgItem(hwnd, ID_TAB);
it->hDC = GetDC(it->hwndItem);
GetWindowRect(hTab, &it->rcItem); // Rectangle of your listbox
it->itemData = 0; // If you want to associate some data with the item
return 0;
case WM_DRAWITEM:
it = (DRAWITEMSTRUCT*) lParam;
switch(it->CtlType == ODT_TAB)
{
case ID_TAB:
OnPaint(it->hDC);
ReleaseDC(hTab, it->hDC);
break;
default:
break;
}
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
};
return 0;
}
Re: Paint on a Tabcontrol
Define "won't work"
BTW, what is the purpose of this code case WM_CREATE:
Code:
// DRAWITEMSTRUCT
ZeroMemory(&it, sizeof(DRAWITEMSTRUCT));
it.CtlType = ODT_TAB;
it.CtlID = IDL_1;
it.itemID = 0;
it.itemAction = ODA_DRAWENTIRE;
it.itemState = ODS_FOCUS; //
it.hwndItem = hTab;
it.hDC = GetDC(it.hwndItem);
GetWindowRect(hwnd, &it.rcItem);
it.itemData = 0;
Note also that the variable it is not declared!
Re: Paint on a Tabcontrol
"Won't work" means that it won't paint, won't draw a line.
I admit that I'm completely lost and I thought that you needed to declare this struct in order to paint on a tabcontrol.
"it" is declared globally only I didn't pasted the right code, sorry for that. I updated it now.
Re: Paint on a Tabcontrol
I do NOT need to declare this struct. And you do not need it either! The DRAWITEMSTRUCT structure is already declared by Microfoft somether in Win32 SDK headers.
Why and what do you want to paint on a tabcontrol?
Can you use MFC framework or only raw Win32 APIs? If the latter then you should have better posted your question in C++ and WinAPI Forum.
And in any case what you need is to search for some sample code used owner drawiing in tabcontrol.
Re: Paint on a Tabcontrol
I want to paint with GDI+ on it.
Code:
Graphics graphics(hdc);
Pen pen(Color(255, 0, 0, 255));
graphics.DrawLine(&pen, 20, 20, 150, 550);
I want to use only raw Win32 APIs and I couldn't find any examples of WinAPI only MFC.
Can you move my thread to the C++ and WinAPI Forum or should I repost it?
Re: Paint on a Tabcontrol
No, I can't. Only moderators can.
Try to ask some of them.
As for an example - try to begin with HOWTO: Change the Background Color of a Tab Control
Re: Paint on a Tabcontrol
Thanks for the help.
I tried to apply the code but I'm doing something wrong, the tabs won't even show up.
Code:
#include <windows.h>
#include <commctrl.h>
#include <iostream>
using namespace std;
#pragma comment(linker, "/subsystem:\"console\" /entry:\"WinMainCRTStartup\"")
#include <gdiplus.h>
using namespace Gdiplus;
#define ID_TAB 113
#define RED RGB(255,0,0)
#define YELLOW RGB(255,255,0)
#define MAGENTA RGB(255,0,255)
#define WHITE RGB(255,255,255)
#define BLUE RGB(0,0,255)
char className[]="TabControl";
HWND hTab;
HINSTANCE hInst;
static DRAWITEMSTRUCT * lpdis;
LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil)
{
MSG messages;
WNDCLASSEX wincl;
hInst = hInstance;
wincl.hInstance=hInstance;
wincl.lpszClassName=className;
wincl.lpfnWndProc=WindowProcedure;
wincl.style=0;
wincl.cbSize=sizeof(WNDCLASSEX);
wincl.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wincl.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
wincl.hCursor=LoadCursor(NULL,IDC_ARROW);
wincl.lpszMenuName=NULL;
wincl.cbClsExtra=0;
wincl.cbWndExtra=0;
wincl.hbrBackground=HBRUSH(COLOR_3DFACE+1);
if(!RegisterClassEx(&wincl))return 0;
HWND windowHandle=CreateWindow(className,"TabControl",
WS_OVERLAPPEDWINDOW,
200,325,480,320,
NULL,NULL,hInstance,NULL);
ShowWindow(windowHandle,SW_SHOW);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
};
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hbr;
COLORREF bkColor;
TCITEM tci;
switch(message)
{
case WM_CREATE:
INITCOMMONCONTROLSEX icce;
icce.dwSize=sizeof(INITCOMMONCONTROLSEX);
icce.dwICC=ICC_TAB_CLASSES;
InitCommonControlsEx(&icce);
hTab=CreateWindow(WC_TABCONTROL,"",
WS_CHILD|WS_VISIBLE|TCS_OWNERDRAWFIXED,
6,0,474,320,
hwnd,
(HMENU)ID_TAB,hInst,NULL);
TCITEM Tab0;
Tab0.mask=TCIF_TEXT;
Tab0.pszText="Tab0";
TabCtrl_InsertItem(hTab,0,&Tab0);
TCITEM Tab1;
Tab1.mask=TCIF_TEXT;
Tab1.pszText="Tab1";
TabCtrl_InsertItem(hTab,1,&Tab1);
TCITEM Tab2;
Tab2.mask=TCIF_TEXT;
Tab2.pszText="Tab2";
TabCtrl_InsertItem(hTab,2,&Tab2);
TCITEM Tab3;
Tab3.mask=TCIF_TEXT;
Tab3.pszText="Tab3";
TabCtrl_InsertItem(hTab,3,&Tab3);
TCITEM Tab4;
Tab4.mask=TCIF_TEXT;
Tab4.pszText="Tab4";
TabCtrl_InsertItem(hTab,4,&Tab4);
return 0;
case WM_DRAWITEM:
lpdis = (LPDRAWITEMSTRUCT) lParam;
if(hTab == lpdis->hwndItem) // is this the tab control?
{
// which tab? first, second...fifth
switch (lpdis->itemID)
{
case 0:
hbr = CreateSolidBrush (RGB(255,0,0)) ;
bkColor = RED;
break;
case 1:
hbr = CreateSolidBrush (RGB(255,0,0)) ;
bkColor = YELLOW;
break;
case 2:
hbr = CreateSolidBrush (RGB(255,0,0)) ;
bkColor = MAGENTA;
break;
case 3:
hbr = CreateSolidBrush (RGB(255,0,0)) ;
bkColor = WHITE;
break;
case 4:
hbr = CreateSolidBrush (RGB(255,0,255)) ;
bkColor = BLUE;
break;
}
tci.mask = TCIF_TEXT;
tci.pszText = "Hello";
tci.cchTextMax = 5;
TabCtrl_GetItem(hTab, lpdis->itemID, &tci);
FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
SetBkColor(lpdis->hDC, bkColor);
TextOut(lpdis->hDC,
lpdis->rcItem.left,
lpdis->rcItem.top,
tci.pszText,
lstrlen(tci.pszText));
}
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
};
return 0;
}
Re: Paint on a Tabcontrol
Did you debug your code?
What does
Code:
CreateWindow(WC_TABCONTROL,"",
WS_CHILD|WS_VISIBLE|TCS_OWNERDRAWFIXED,
6,0,474,320,
hwnd,
(HMENU)ID_TAB,hInst,NULL);
return?
What do all these
Code:
TabCtrl_InsertItem(hTab, i, &Tabi);
return?
Re: Paint on a Tabcontrol
They are ok, returning the indexes of the tabs.
Actually it not only breaks out of the switch() but it breaks out of the WM_DRAWITEM and never goes to the rest of the code, that is the problem.
Edit. The tabs won't get created because of the TCS_OWNERDRAWFIXED style. But I need this style to repaint the background.