NO

Author Topic: Ownerdraw-Buttons second edition  (Read 6805 times)

pitter2206

  • Guest
Ownerdraw-Buttons second edition
« on: February 01, 2011, 01:52:59 pm »
Hi,

I need your help again, I think.

With help from some experts here in the forum, my first userdefined menue is nearly ready.

What is missing:

Reading the measurements of the buttons out of my textfile and
writing the text on the buttons, written in the textfile too.

This is what I´ve done until now:
Code: [Select]
#include <windows.h>
#include <wchar.h>

/** Globals ********************************************************/
#define WIN32_LEAN_AND_MEAN
#define IDM_BTN1 6010
#define N 14 // Number of Buttons, incl.  6 rows comments in textfile
#define LINELEN_MAX 200
#define BUTTONMAX 10 //Number of Buttons, shown in menue

BOOL WINAPI CheckRemoteDebuggerPresent( HANDLE hProcess, PBOOL pbDebuggerPresent ){ // Routine für CE5!
if( pbDebuggerPresent != NULL )
*pbDebuggerPresent = FALSE;
return TRUE;
}

LRESULT WINAPI WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
void OnDestroy(HWND hwnd);
void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem);


TCHAR szAppName[] = L"GPW_Menue";
TCHAR szFrameClass[] = L"GPW_Class";
TCHAR fname[MAX_PATH];
char fname_2[MAX_PATH];

wchar_t  *fmtw = (L"%200l[^\n]\n %200l[^\n]\n %200l[^\n]\n");


HANDLE hInst;

HWND hFrame;
HWND  hWndBtn0, hWndBtn1, hWndBtn2, hWndBtn3, hWndBtn4, hWndBtn5;
HWND  hWndBtn6, hWndBtn7, hWndBtn8, hWndBtn9, hWndBtn10;

typedef struct button Button;
struct button
{
   wchar_t text[LINELEN_MAX+1];
   wchar_t pic[LINELEN_MAX+1];
   wchar_t link[LINELEN_MAX+1];
};
Button buttons[N] = {0};

HBITMAP hBM[BUTTONMAX];
HBITMAP background;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wc;
MSG msg;


wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szFrameClass;
   wc.style = CS_VREDRAW | CS_HREDRAW;

if (!RegisterClass(&wc)) {
MessageBox(NULL,L"Error with RegisterClass",0,0);
return 0;
}

hInst = hInstance;

hFrame = CreateWindowEx(WS_EX_CAPTIONOKBTN, szFrameClass, szAppName,
WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInst, NULL);

if(!hFrame) return 0;

ShowWindow(hFrame, nCmdShow);
UpdateWindow(hFrame);
 
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT WINAPI WndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch(wMsg) {
case WM_COMMAND: return OnCommand(hwnd,(int)LOWORD(wParam),(HWND)lParam,(UINT)HIWORD(wParam)),0;
case WM_CREATE: return OnCreate(hwnd,(LPCREATESTRUCT)lParam),0;
case WM_DESTROY: return OnDestroy(hwnd),0;
case WM_DRAWITEM: return (OnDrawItem(hwnd,(const DRAWITEMSTRUCT*)lParam),0);

default:
return DefWindowProc(hwnd, wMsg, wParam, lParam);
}
}

BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
int n = 3, // Anzahl der zu einem Datensatz zugehörigen Zeilen.
i = 0; // Index und Zähler fürs Strukturarray.
 
 FILE* fp = fopen ( fname_2, "r" );
if ( fp == NULL ) // Wenn die Textdatei fehlt, bringe Fehlermeldung
{
MessageBox(NULL, L"Zugehörige Textdatei fehlt!", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
}
    while ( !feof(fp) )
{
        if ( i == N ){
MessageBox(NULL, L"Zugehörige Textdatei ist beschädigt! ", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
return (0);
             break;
         }
if (n != fwscanf(fp, fmtw, &buttons[i].text, buttons[i].pic, buttons[i].link)){
  MessageBox(NULL, L"Zugehörige Textdatei ist nicht vollständig! ", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
             break;
  }
i++;
     }
    fclose ( fp );


OutputDebugString(L"WM_CREATE");

/*********** Buttons**************/

/***********Row 1***************/
if (_wfopen(buttons[0].link , L"r") != 0){ // prüft ob die auszuführende Exe vorhanden ist. Falls nicht, wird der Button nicht angezeigt.
hWndBtn0 = CreateWindow( L"BUTTON", L"Button 1", WS_VISIBLE | BS_OWNERDRAW, 0, 33, 239, 62, hwnd, (HMENU)IDM_BTN1, hInst, NULL);
hBM[0] = SHLoadDIBitmap(buttons[0].pic);
}
if (_wfopen(buttons[1].link , L"r") != 0){
hWndBtn1 = CreateWindow( L"BUTTON", L"Button 2", WS_VISIBLE | BS_OWNERDRAW, 241, 33, 239, 62, hwnd, (HMENU)(IDM_BTN1+1), hInst, NULL);
hBM[1] = SHLoadDIBitmap(buttons[1].pic);
}
/*

following some other buttons

*/

/*********** Background  *********************/
HWND hwndback = CreateWindow( L"STATIC", NULL, WS_VISIBLE | WS_CHILD |SS_BITMAP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, hwnd, NULL, hInst, NULL);
background = SHLoadDIBitmap(buttons[11].pic);
SendMessage(hwndback,(UINT)STM_SETIMAGE, (WPARAM)IMAGE_BITMAP,(LPARAM)background);

}

void OnDestroy(HWND hwnd)
{
OutputDebugString(L"WM_DESTROY");
for (int i = 0; i < BUTTONMAX; i++)
if (hBM[i]) DeleteObject(hBM[i]);
PostQuitMessage(0);
}

void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch(id)

{
/********************Row 1***************/
case IDM_BTN1:
CreateProcess(buttons[0].link,NULL,0,0,FALSE,0, 0, 0, NULL, NULL );
PostMessage(hwnd, WM_DESTROY, 0, 0L);
return;
case IDM_BTN1+1:
     CreateProcess(buttons[1].link, NULL,0,0,FALSE,0, 0,0,NULL,NULL  );
PostMessage(hwnd, WM_DESTROY, 0, 0L);
return;
/*

following some other buttons

*/

}
}

void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
{
RECT rc;
HDC hdc;
HDC hdcMem;
HBITMAP hBM0;
BITMAP bm;
int nIdx;

if (lpDrawItem->CtlID < IDM_BTN1 || lpDrawItem->CtlID > (IDM_BTN1+BUTTONMAX))
return;

nIdx = lpDrawItem->CtlID-IDM_BTN1;
rc = lpDrawItem->rcItem;
hdc = lpDrawItem->hDC;
hBM0 = hBM[nIdx];

hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBM0);
GetObject(hBM0, sizeof(bm), &bm);
if (lpDrawItem->itemState & ODS_SELECTED) { //  clicked
BitBlt(hdc, -2, -2, bm.bmWidth-0, bm.bmHeight-0, hdcMem, -2, -2, SRCCOPY); // paints the button
DrawEdge(lpDrawItem->hDC, &rc, EDGE_SUNKEN, BF_TOPLEFT);
}
else {
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); // normal Button
// DrawEdge(lpDrawItem->hDC, &rc, EDGE_RAISED, BF_RECT); // not needed this time
}
DeleteDC(hdcMem);
}


Would you please help me again with completing the menue?


Thank you!

Greetings Peter

« Last Edit: February 01, 2011, 01:55:38 pm by pitter2206 »

pitter2206

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #1 on: February 02, 2011, 05:53:10 pm »
To use the buttontext, I think I can use the DC from 'void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem) and use DrawText()

But how can I use buttons.text?

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1940
Re: Ownerdraw-Buttons second edition
« Reply #2 on: February 03, 2011, 12:02:25 pm »
Something like this:
Code: [Select]
DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_CENTER);
Some tips:
If you define hWndBtn as array
Code: [Select]
HWND hWndBtn[N];You can use it in OnCreate() function like this:
Code: [Select]
for (i=0; i<BUTTONMAX; i++) {
int x,y;
x = (i%2)*120;
y = (i/2)*63;
if (GetFileAttributes(buttons[0].link) != -1) {
//if (!buttons[i].text[0]) break; // done ?
hWndBtn[i] = CreateWindow( L"BUTTON", "", WS_CHILD|WS_VISIBLE|BS_OWNERDRAW, x, y, 120, 62, hwnd, (HMENU)(IDM_BTN1+i), hInst, NULL);
}
}
« Last Edit: February 03, 2011, 01:06:07 pm by timovjl »
May the source be with you

pitter2206

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #3 on: February 04, 2011, 02:59:03 pm »
Great!!!

Thank you again for your help.  :)

I think, your last tipp won´t work for me, because there are 4 different buttonsizes I have to use. That would work fine, if it would be possible to work with only one size...

The buttontext is shown now out of the textfile...
I added this:

Code: [Select]
SetBkColor (hdc, TRANSPARENT);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(255,255,255));
DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_LEFT | DT_VCENTER);

Just now I try to change the fontsize. I hope it will work. ;)


But... another question:

Is it possible to work with DrawText() and set the buttontext 50 pixel from the left side? Just something like an offset of 50 Pixel?
I found nothing like that... :(
That would be nice, because at the left side is shown an embedded icon in the bitmap and it would be nice, if the text is show at the same place on every button...

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1940
Re: Ownerdraw-Buttons second edition
« Reply #4 on: February 04, 2011, 07:17:22 pm »
That text position is in RECT rc.
Just insert 50 to rc.left.
« Last Edit: February 07, 2011, 07:37:04 pm by timovjl »
May the source be with you

pitter2206

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #5 on: February 04, 2011, 10:41:23 pm »
ah thanks... I´ll give it a try...

pitter2206

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #6 on: February 05, 2011, 01:10:03 pm »
I think I am too fool to do it...

Whether to change the font and size nor the text position.

To change the font I tried it like that:
Code: [Select]
/* draw the text on the button */
DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_CENTER| DT_VCENTER);

/* Font ans size */
for (i=0; i<BUTTONMAX; i++) {
  SendDlgItemMessage(hwnd, IDM_BTN1+i, WM_SETFONT, (WPARAM)hFont, TRUE);
}

DeleteDC(hdcMem);
}

The text will be drawn to all buttons excepting the button IDM_BTN1 (IDM_BTN1+0).
And... the last button flares all time....

What the hell is going wrong???

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1940
Re: Ownerdraw-Buttons second edition
« Reply #7 on: February 05, 2011, 03:12:54 pm »
Move that font changing code to WM_CREATE / OnCreate block after creating buttons.

Tip:
Empty text line:
Use marker for empty text and clear it after reading it.
Code: [Select]
if (buttons[i].text[0] == ';') // empty text marker
buttons[i].text[0] = 0;
« Last Edit: February 06, 2011, 08:41:28 am by timovjl »
May the source be with you

pitter2206

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #8 on: February 05, 2011, 03:42:33 pm »
hmmm... the fontface and size is working, but whether textcolor nor the transparent background is working...  ???

Edit:
It works now fine with it.


Another Question comes arround:

I read my textfile:
Code: [Select]
FILE* fp = fopen ( fname_2, "r" );
if ( fp == NULL ) // Wenn die Textdatei fehlt, bringe Fehlermeldung
{
MessageBox(NULL, L"Zugehörige Textdatei fehlt!", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
}
    while ( !feof(fp) )
{
        if ( i == N ){
MessageBox(NULL, L"Zugehörige Textdatei ist beschädigt! ", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
return (0);
            break;
        }
if (n != fwscanf(fp, fmtw, &buttons[i].text, buttons[i].pic, buttons[i].link)){
  MessageBox(NULL, L"Zugehörige Textdatei ist nicht vollständig! ", L"Fehler", MB_SETFOREGROUND);
DestroyWindow(hwnd);
PostQuitMessage(0);
            break;
  }
i++;
    }
    fclose ( fp );

Because of that, it is nessessary, that I have 3 lines for each button.
buttons.text
buttons.pic
buttons.link

Some buttons need no buttons.text, but I don´t know how to destroy the buttons.text för these buttons...
« Last Edit: February 05, 2011, 09:57:31 pm by pitter2206 »

saliha

  • Guest
Re: Ownerdraw-Buttons second edition
« Reply #9 on: February 26, 2011, 08:56:10 am »
Thanks for the code..
Hope will workout soon..