Προς το περιεχόμενο

Win32 API + C + UpDown controls


Προτεινόμενες αναρτήσεις

Δημοσ.

Βασικά έχω 2 ερωτήσεις:

 

1) Είναι όντως τόσο πολύπλοκο να διαχειριστεί κανείς spinboxes (updown control + edit control) στο Win32 API με σκέτη C (χωρίς χρήση του UDS_SETBUDDYINT, γιατί π.χ. θέλω να περιέχει και floats το edit-box, και ως βήμα και ως αποτέλεσμα, αντί για σκέτους int) ;

 

Κατέληξα να φτιάξω δική μου, εσωτερική, απεικόνιση του spin-box η οποία μαζί με τις ας τις πούμε μεθόδους της λειτουργεί ως ενδιάμεσο layer για αποστολή & λήψη πληροφοριών προς και από τα actual controls του Dialog, για να μπορώ να διαχειρίζομαι uniformly τα διάφορα spinboxes του Dialog.

 

 

 

>
/**
* Internal representation of a custom spin control, consisting
* of an updown and an edit-box control, with the following mandatory
* prerequisites:
* -	the updown is bonded to the edit-box with the UDS_AUTOBUDDY style
* -	the updown does NOT have the UDS_SETBUDDYINT style set
*/
typedef struct TDlgSpin {
enum 	{ DLGSPIN_TSTEP_INT = 0, DLGSPIN_TSTEP_FLOAT } udTStep;	// type of step 
int 	edId;
TCHAR	edText[ MAXLEN_DLGSPIN_TEXT ];
int 	udId;
int    udHi;
int    udLo;
int 	udPos;
union 	{ int Int; float Float;} udStep;
int	udDelta;
} TDlgSpin;

/*******************************************************//**
*
***********************************************************
*/
BOOL dlgSpin_set(
TDlgSpin *spin,
int	udTStep,
int 	edId,
TCHAR	*edText,
int 	udId,
int 	udHi,
int 	udLo,
int 	udPos,
float	udStep,
int	udDelta
)
{
if ( !spin )
	return FALSE;

spin->udTStep 	= udTStep;

spin->edId 	= edId;
_tcsncpy(spin->edText, edText, MAXLEN_DLGSPIN_TEXT );
spin->edText[ _tcslen(spin->edText) ] = TEXT('\0');

spin->udId 	= udId;
spin->udHi 	= udHi;
spin->udLo 	= udLo;
spin->udPos 	= udPos;
if ( udTStep == DLGSPIN_TSTEP_FLOAT )
	spin->udStep.Float = udStep;
else
	spin->udStep.Int = (int)udStep;

spin->udDelta 	= udDelta;

return TRUE;
}

/*******************************************************//**
*
***********************************************************
*/
BOOL dlgSpin_toDlg( const TDlgSpin *spin, HWND hDlg )
{
if ( NULL == hDlg || !spin )
	return FALSE;

SetDlgItemText( hDlg, spin->edId, spin->edText );
SendDlgItemMessage(
	hDlg,
	spin->udId,
	UDM_SETRANGE,
	(WPARAM)0,
	MAKELPARAM(spin->udHi, spin->udLo)
);
SendDlgItemMessage(
	hDlg,
	spin->udId,
	UDM_SETPOS,
	(WPARAM)0,
	MAKELPARAM(spin->udPos, 0)
);

return TRUE;
}

/*******************************************************//**
*
***********************************************************
*/
BOOL DlgUpdateSpin( HWND hDlg, const TDlgSpin *spin )
{
TCHAR 	txt[1024] = { TEXT('\0') };
const int txtsize = sizeof(txt) / sizeof(TCHAR);
int 	ntchars   = 0;

/* sanity check */
if ( NULL == hDlg || !spin )
	return FALSE;

// get the text of the edit-box
GetDlgItemText( hDlg, spin->edId, txt, txtsize);

// convert text to number & apply spin->udStep (according to spin->udDelta)
if ( DLGSPIN_TSTEP_FLOAT == spin->udTStep )
{
	float resFloat = _tstof(txt);
	if ( spin->udDelta > 0 )		// user pressed up-arrow
		resFloat += spin->udStep.Float;
	else if ( spin->udDelta < 0 )		// user pressed down-arrow
		resFloat -= spin->udStep.Float;

	// auto-fix result to range-boundaries, if necessary
	if ( resFloat < (float)(spin->udLo) )
		resFloat = (float)(spin->udLo);
	else if ( resFloat > (float)(spin->udHi) )
		resFloat = (float)(spin->udHi);

	// Convert the (float) result back to text & put it in the edit-box
	ntchars = my_snprintf(txt, txtsize, TEXT("%.2f"), resFloat);
	if ( ntchars >= txtsize ) {
		myINFO_BOX( TEXT("Buffer overrun!") );
		return FALSE;
	}
}
else
{
//msgboxf( TEXT("Info"), TEXT("iDelta: %d, udStep.Int: %d"), spin->udDelta, spin->udStep.Int);

	int resInt = _tstoi(txt);
	if ( spin->udDelta > 0 )		// user pressed up-arrow
		resInt += spin->udStep.Int;
	else if ( spin->udDelta < 0 )		// user pressed down-arrow
		resInt -= spin->udStep.Int;

	// auto-fix result to range-boundaries, if necessary
	if (resInt < spin->udLo )
		resInt = spin->udLo;
	else if (resInt > spin->udHi)
		resInt = spin->udHi;

	// Convert the (int) result back to text & put it in the edit-box
	ntchars = my_snprintf(txt, txtsize, TEXT("%d"), resInt);
	if ( ntchars >= txtsize ) {
		myINFO_BOX( TEXT("Buffer overrun!") );
		return FALSE;
	}
}

SetDlgItemText( hDlg, spin->edId, txt );

return TRUE;
}

κλπ, κλπ

 

 

 

2) Στην τεκμηρίωση αναφέρει πως τα ud-controls στέλνουν WM_VSCRL ή WM_HSCRL messages, αλλά εγώ τα πιάνω με το WM_NOTIFY που προηγείται, για να πάρω το iDelta και να αυξήσω/μειώσω ανάλογα το κείμενο του buddy...

 

>
...
	case WM_NOTIFY:
		switch( ((LPNMHDR)lParam)->code )
		{
			int  	udId;
			TDlgSpin spin;

			case UDN_DELTAPOS:
				udId 	= ((LPNMHDR)lParam)->idFrom;
		           if ( UD_TAID == udId )
				{
					memcpy( &spin,
						&g_tadataDlg.identification.spinTAID,
						sizeof( TDlgSpin )
					);
					spin.udDelta = ((LPNMUPDOWN)lParam)->iDelta;
//msgboxf( TEXT("Info"), TEXT("iDelta: %d"), spin.udDelta);
//						DlgUpdateSpin( hDlg, &spin );
				}
				break;
...

Με αυτό κάνω τη δουλειά μου, χρειάζεται να ελέγξω και το WM_VSCRL; Αν ναι, γιατί;

  • Απαντ. 32
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσιευμένες Εικόνες

Δημοσ.

Τι όχι; Τι εννοείς όταν λες κλάση; Είδες ότι αναφέρομαι σε C;

 

Οπως φτιαχνεις το main window (νεα wndclass/ex registerclass, wndproc etc) ετσι θα φτιαξεις μια κλαση που θα εχει μεσα μονο ενα edit και το updown το οποιο θα επικοινωνει μεσου Get/SendMessage με το main window

Δημοσ.

Οπως φτιαχνεις το main window (νεα wndclass/ex registerclass, wndproc etc) ετσι θα φτιαξεις μια κλαση που θα εχει μεσα μονο ενα edit και το updown το οποιο θα επικοινωνει μεσου Get/SendMessage με το main window

 

Ωραίο! Δεν το είχα σκεφτεί. Thanks!

 

Αν και θα πρέπει να ρίξω διάβασμα γιατί δεν θυμάμαι τίποτα.

 

EDIT:

 

Πες μου και για το WM_VSCRL μιας που σε βρήκα εύκαιρο, το χρειάζομαι; Θα με εξυπηρετήσει σε κάτι;

Δημοσ.

 

Πες μου και για το WM_VSCRL μιας που σε βρήκα εύκαιρο, το χρειάζομαι; Θα με εξυπηρετήσει σε κάτι;

 

Με το msdn δουλευω, δεν τα ξερω ολα απ'εξω. Τεσπα θα φτιαξω ενα τετοιο control για εξασκηση και θα το κανω ποστ

Δημοσ.

Με το msdn δουλευω, δεν τα ξερω ολα απ'εξω. Τεσπα θα φτιαξω ενα τετοιο control για εξασκηση και θα το κανω ποστ

Όχι ρε συ, δεν χρειάζεται. Θα τα βρω, ήταν πολύ ωραία ιδέα το wndclass.

 

Εννοώ δεν χρειάζεται να ταλαιπωρηθείς εσύ για μένα (άλλο αν θες να το κάνεις κι εσύ για φρεσκάρισμα).

Δημοσ.

Να κάνω μια άσχετη ερώτηση καθαρά για κουβεντούλα.

 

Γιατί χρησιμοποιείς C γιατί κάτι τέτοιο;

Και επίσης.

Αυτό το κανεις κάπου επαγγελματικά η χομπυστικά;

Δημοσ.

Να κάνω μια άσχετη ερώτηση καθαρά για κουβεντούλα.

 

Γιατί χρησιμοποιείς C γιατί κάτι τέτοιο;

Και επίσης.

Αυτό το κανεις κάπου επαγγελματικά η χομπυστικά;

Χομπίστικα. Χρησιμοποιώ C γιατί θέλω να φρεσκάρω τη μνήμη μου στο pure Win32 API. Για να είμαι απολύτως ειλικρινής, ξεκίνησα γιατί ήθελα να επιβεβαιώσω/διαψεύσω την απόφασή μου πολλά χρόνια πριν να μην ασχοληθώ ποτέ ξανά με Win32 API + C όταν πρωτο-προγραμμάτισα σε GTK+. 1-2 μέρες έχω που άρχισα να ξανασκαλίζω πάλι το Win32 API, και μέχρι στιγμής νομίζω είχα πάρει σωστή απόφαση τότε :lol:

Δημοσ.

Όχι ρε συ, δεν χρειάζεται. Θα τα βρω, ήταν πολύ ωραία ιδέα το wndclass.

 

Εννοώ δεν χρειάζεται να ταλαιπωρηθείς εσύ για μένα (άλλο αν θες να το κάνεις κι εσύ για φρεσκάρισμα).

Τελικά ίσως και να μην είναι και τόσο καλή ιδέα ξεχωριστού wndclass για custom control, εκτός αν φταίει που δεν έχω ακουμπήσει το winapi για χρόνια και η λύση αυτή μου φαίνεται πολύ πιο περίπλοκη από αυτήν που έχω παραθέσει στο 1ο ποστ.

 

Έριξα λίγο διάβασμα σήμερα και η αλήθεια είναι πως περισσότερο χάθηκα, παρά βοηθήθηκα. Εννοώ πως μάλλον μου δημιουργήθηκαν περισσότερες απορίες από τις αρχικές μου.

 

Για παράδειγμα, η wndclass του custom control πρέπει να είναι global ή local? Χρειάζεται να χρησιμοποιήσω InitCommonControls() / InitCommonControlsEx() για αυτό το custom control ή όχι; Σε γενικές γραμμές, για κάθε απορία για την οποία διαβάζω, γεννιόνται άλλες 1-2 που θέλουν κι άλλο διάβασμα, με αποτέλεσμα στο τέλος σχεδόν να έχω ξεχάσει από ποια απορία μου ξεκίνησα να διαβάζω :lol:

 

Πέρα από τα παραπάνω, έχω την εντύπωση πως το overhead δημιουργίας callback CustomControlProc() που θα διαχειρίζεται τα events του custom control θα είναι πολύ μεγαλύτερο από αυτό που κάνω στο 1ο ποστ.

 

@παπι: Αν τελικά βρεις χρόνο & κέφι να γράψεις κώδικα δημιουργίας και διαχείρισης ενός custom spinner control, ανέβασέ τον αν θες και στο νήμα, να πάρω ιδέες. Προς το παρόν θα το συνεχίσω με τον τρόπο του 1ου ποστ (μου φαντάζει πολύ απλός τελικά :lol:)

 

Για όποιον ενδιαφέρεται, ξεκίνησα να διαβάζω από αυτές τις 2 σελίδες:

 

1. http://msdn.microsof...v=vs.85%29.aspx

2. http://msdn.microsof...v=vs.85%29.aspx

 

αλλά διάβασα και μερικές ντουζίνες ακόμα, που περισσότερο με μπέρδεψαν παρά με βοήθησαν.

Π.χ.

http://stackoverflow...tcommoncontrols

http://zetcode.com/t...customcontrols/

Δημοσ.

Μπορει να εχει αρκετα bugs αλλα δε βαριεσαι.

 

main.cpp

>#include "etc.h"
#include "updown_edit.h"

PWSTR strs[] = {
L"Ενα",
L"Δυο",
L"Τρια",
L"Τεσσερα"

};
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE,PSTR,int)
{
WNDCLASSEX sex ={ 0 };
HWND		hWnd;
MSG			msg;
sex.cbSize			= sizeof(sex);
sex.hbrBackground	= (HBRUSH) COLOR_WINDOW;
sex.hInstance		= hInst;
sex.hCursor			= LoadCursor(NULL, IDC_ARROW);
sex.lpfnWndProc		= WndProc;
sex.style			= (CS_HREDRAW | CS_VREDRAW);
sex.lpszClassName	= L"mainCls";

RegisterClassEx(&sex);
hWnd = CreateWindow(L"mainCls",L"Main Window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,hInst,0);
ShowWindow(hWnd,SW_SHOW);
while(GetMessage(&msg,0,0,0) > 0)
{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}


return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND hCtrl;
UPDOWNEDIT_INITSTRUCT_NUMERIC num;
UPDOWNEDIT_INITSTRUCT_STRING_ARRAY str;
switch(msg)
{
case WM_CREATE:
	InitMyControl();
	hCtrl = CreateWindow(UPDOWNEDIT_CLASS,0,WS_VISIBLE | WS_CHILD,100,100,120,27,hWnd,(HMENU)100,0,0);
	num.flag = UINF_FLOAT;
	
	num.f.end = 10.0f;
	num.f.pos = 7.0f;
	num.f.start = 5.0f;
	num.f.factor = 0.1f;
	UpdownEdit_InitNumeric(hCtrl,&num); // set numeric updown

	hCtrl = CreateWindow(UPDOWNEDIT_CLASS,0,WS_VISIBLE | WS_CHILD,100,200,120,27,hWnd,(HMENU)101,0,0);

	str.count	= 4;
	str.pos		= 0;
	str.pStrings = strs;
	UpdownEdit_InitArray(hCtrl,&str);


	CreateWindow(UPDOWNEDIT_CLASS,0,WS_VISIBLE | WS_CHILD,100,300,120,27,hWnd,(HMENU)102,0,0);
	break;
case WM_CLOSE:
	PostQuitMessage(0);
	break;
default:
	return DefWindowProc(hWnd,msg,wParam,lParam);
}
return 0;
}

 

 

 

updown_edit.h

>#pragma once
#include "etc.h"
#include <stdio.h>
#include <tchar.h>

#define UPDOWNEDIT_CLASS L"updownedit"


//commands
#define WMC_VALUE_CHANGE 100

//messages
#define UDEM_INIT			(WM_USER + 1)



#define UINF_FLOAT		1
#define UINF_INTEGER	2

#define UDET_NUMERIC	1
#define UDET_ARRAY		2


typedef struct
{
int flag;
struct 
{
	float start;
	float end;
	float pos;
	float factor;
}f;
struct
{
	int start;
	int end;
	int pos;
	int factor;
}i;

}UPDOWNEDIT_INITSTRUCT_NUMERIC;

typedef struct
{
PTCHAR *pStrings;
int count;
int pos;

}UPDOWNEDIT_INITSTRUCT_STRING_ARRAY;




#define UpdownEdit_InitNumeric(hCtrl,pUin) \
SendMessage(hCtrl,UDEM_INIT,UDET_NUMERIC, (LPARAM)pUin)
#define UpdownEdit_InitArray(hCtrl,pUisa) \
SendMessage(hCtrl,UDEM_INIT,UDET_ARRAY,(LPARAM)pUisa)

#ifndef __cplusplus
void InitMyControl();
#else
extern "C" void InitMyControl();
#endif

 

 

updown_edit.c

>

#include "updown_edit.h"

#define ID_EDIT			100
#define ID_UPDOWN		101
typedef struct
{
int										type;
UPDOWNEDIT_INITSTRUCT_NUMERIC			numeric;
UPDOWNEDIT_INITSTRUCT_STRING_ARRAY		strings;

}UPDOWNEDIT_INTERNAL_DATA;


//internal
LRESULT CALLBACK UpDonwProc(HWND hWnd,UINT msg,  WPARAM wParam,LPARAM lParam);
void OnCreate(HWND hWnd,CREATESTRUCT* pcs);
void OnDestroy(HWND hWnd);
void changeValue(HWND hWnd,int factor);

void InitMyControl()
{
WNDCLASSEX     sex	= { 0 };
sex.cbSize			= sizeof(sex);
sex.lpszClassName	= UPDOWNEDIT_CLASS;
sex.hCursor			= LoadCursor(NULL,IDC_ARROW);
sex.lpfnWndProc		= UpDonwProc;
RegisterClassEx(&sex);

}

LRESULT CALLBACK UpDonwProc(HWND hWnd,UINT msg,  WPARAM wParam,LPARAM lParam)
{

int									factor;
UPDOWNEDIT_INTERNAL_DATA			*pInternalData;
UPDOWNEDIT_INITSTRUCT_STRING_ARRAY	*pUisa;
UPDOWNEDIT_INITSTRUCT_NUMERIC		*pUin;
switch(msg)
{
case UDEM_INIT:
	pInternalData = (UPDOWNEDIT_INTERNAL_DATA*) GetWindowLong(hWnd,GWLP_USERDATA);
	switch(wParam)
	{
	case UDET_ARRAY:
		pUisa = (UPDOWNEDIT_INITSTRUCT_STRING_ARRAY*) lParam;
		pInternalData->strings.count	= pUisa->count;
		pInternalData->strings.pos		= pUisa->pos;
		pInternalData->strings.pStrings = malloc(pUisa->count * sizeof(void*));
		for(factor = 0; factor < pUisa->count; factor++)
		{
#if _UNICODE
			pInternalData->strings.pStrings[factor] = wcsdup(pUisa->pStrings[factor]);
#else
			pInternalData->strings.pStrings[factor] = strdup(pUisa->pStrings[factor]);
#endif
		}
		pInternalData->type = UDET_ARRAY;
		changeValue(hWnd,0);
		break;
	case UDET_NUMERIC:
		pUin = (UPDOWNEDIT_INITSTRUCT_NUMERIC*) lParam;
		memcpy(&pInternalData->numeric,pUin,sizeof(UPDOWNEDIT_INITSTRUCT_NUMERIC));
		pInternalData->type = UDET_NUMERIC;
		changeValue(hWnd,0);
		break;
	}
	break;
case WM_CREATE:
	OnCreate(hWnd,(CREATESTRUCT*)lParam);
	break;
case WM_DESTROY:
	OnDestroy(hWnd);
	break;
case WM_GETTEXT:
	GetDlgItemText(hWnd,ID_EDIT,(LPWSTR)lParam,wParam);
	break;
case WM_NOTIFY:
	switch( ((NMHDR*)lParam)->code)
	{
	case UDN_DELTAPOS:
		if( ((NMUPDOWN*)lParam)->iDelta > 0)
			factor = -1;
		else if( ((NMUPDOWN*)lParam)->iDelta < 0)
			factor = 1;
		changeValue(hWnd,factor);
		SendMessage(GetParent(hWnd),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(hWnd),WMC_VALUE_CHANGE),(LPARAM)hWnd); // send wm
		break;
	}
	break;
case WM_MOUSEWHEEL:
	if( (short)HIWORD(wParam) > 0) factor = -1;
	else if( (short)HIWORD(wParam) < 0) factor = 1;
	else factor = 0.0;
	changeValue(hWnd,factor);
	SendMessage(GetParent(hWnd),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(hWnd),WMC_VALUE_CHANGE),(LPARAM)hWnd); // send wm
	break;
default:
	return DefWindowProc(hWnd,msg,wParam,lParam);
}
return 0;
}
void OnCreate(HWND hWnd,CREATESTRUCT* pcs)
{
UPDOWNEDIT_INTERNAL_DATA *pInteralData;
CreateWindow(WC_EDIT,L"Unset",WS_CHILD | WS_VISIBLE,0,0,pcs->cx - 30,pcs->cy,hWnd,(HMENU)ID_EDIT,0,0);
CreateWindow(UPDOWN_CLASS,0,WS_CHILD | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT,pcs->cx - 30,0,30,30,hWnd,(HMENU)ID_UPDOWN,0,0);

pInteralData = malloc(sizeof(UPDOWNEDIT_INTERNAL_DATA));
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG) pInteralData);
}
void changeValue(HWND hWnd,int factor)
{
char cBuf[120];
float fTmp;
int iTmp;

UPDOWNEDIT_INTERNAL_DATA *pInteralData;

pInteralData = (UPDOWNEDIT_INTERNAL_DATA*) GetWindowLongPtr(hWnd,GWLP_USERDATA);

if(pInteralData->type == UDET_NUMERIC)
{
	if( pInteralData->numeric.flag == UINF_FLOAT )
	{
		fTmp = pInteralData->numeric.f.pos + (pInteralData->numeric.f.factor * (float)factor);
		if(fTmp > pInteralData->numeric.f.end
			||fTmp < pInteralData->numeric.f.start)
			return;
		pInteralData->numeric.f.pos = fTmp;
		sprintf(cBuf,"%f",fTmp);
		SetDlgItemTextA(hWnd,ID_EDIT,cBuf);
	}
	else if( pInteralData->numeric.flag == UINF_INTEGER )
	{
		//doto
	}
}
else if(pInteralData->type == UDET_ARRAY)
{
	iTmp = pInteralData->strings.pos + factor * -1;
	if(iTmp < 0
		||iTmp > pInteralData->strings.count)
		return;
	pInteralData->strings.pos = iTmp;
	SetDlgItemText(hWnd,ID_EDIT,pInteralData->strings.pStrings[iTmp]);
}
}

void OnDestroy(HWND hWnd)
{
UPDOWNEDIT_INTERNAL_DATA *pInteralData;
int i;
pInteralData = (UPDOWNEDIT_INTERNAL_DATA*) GetWindowLongPtr(hWnd,GWLP_USERDATA);
if(pInteralData->type == UDET_ARRAY)
{
	for(i = 0; i < pInteralData->strings.count; i++)
	{
		free(pInteralData->strings.pStrings[i]);
	}
	free(pInteralData->strings.pStrings);
}
free(pInteralData);
}

 

 

etc.h

>

#pragma once

#include <windows.h>
#include <CommCtrl.h>
#include <WindowsX.h>
#pragma comment(lib,"ComCtl32.Lib")

#pragma comment(linker,"\"/manifestdependency:type                  = 'win32' \
                                             name                  = 'Microsoft.Windows.Common-Controls' \
                                             version           	= '6.0.0.0' \
                                             processorArchitecture = '*' \
                                             publicKeyToken        = '6595b64144ccf1df' \
                                             language              = '*'\"")
									  	

 

 

Το τελευταιο εχει να κανει με το initcommonctrlex, εγω δεν το καλω, αλλα φτιαχνω ενα embeded manifest για τα commctl v6, ψαξε πως το κανεις αυτο για τον compiler που εχεις

 

http://www.youtube.com/watch?v=NhLqO4Q0P64

 

Δημοσ.

Thanks για τον κώδικα!

 

Πιστεύω πως όντως τελικά παραείναι πολύπλοκος.

 

Προς το παρόν θα αρκεστώ στον τρόπο του 1ου ποστ, που προσωπικά τον βρίσκω πολύ απλούστερο κι εξίσου λειτουργικό για τις ανάγκες μου.

 

Εκτός αν τα πάρω κρανίο πάλι και ξαναγυρίσω στο GTK :lol: ...

 

ΥΓ. btw, εκεί τα SpinButtons (έτσι τα λέει) συμπεριλαμβάνονται στα στάνταρ widgets (έτσι λέει τα controls) με αποτέλεσμα η συνολική τους διαχείριση να είναι σκάρτες 20 γραμμές κώδικα: http://developer.gno...SpinButton.html

Δημοσ.

Δεν ανοίγω άλλο νήμα, νομίζω δεν υπάρχει λόγος... ας τα έχουμε όλα σε αυτό.

 

Επειδή έχω πήξει στο διάβασμα, θυμάται κανείς απέξω αν πρέπει να καταστρέφουμε μόνοι μας controls που δημιουργούμε με CreateWindowEx() στο WM_INITDIALOG message ενός modal Dialog;

 

Συγκεκριμένα έχω αυτή την ρουτίνα που δημιουργεί ένα Tooltip στο δοθέν item ενός Dialog...

 

 

 

>
/*******************************************************//**
* @brief		Create a tooltip for an item in a dialog box.
*
* @param hDlg		Window handle of the dialog box.
* @param idItem	Identifier of an dialog box item.
* @param pszText	String to use as the tooltip text.
*
* @return		The handle to the tooltip.
***********************************************************
*/
HWND DlgCreateTooltip( HWND hDlg, int idItem, TCHAR *pszText )
{
HWND hItem		= NULL;
HWND hTooltip		= NULL;
TOOLINFO toolinfo	= { 0 };		// near initialization

if (!hDlg || !idItem || !pszText)
	return NULL;

/* Create the tooltip window (g_hInst is the global instance handle). */
hItem      = GetDlgItem(hDlg, idItem);
hTooltip = CreateWindowEx(
		0,
		TOOLTIPS_CLASS, NULL,
		WS_POPUP | TTS_ALWAYSTIP, // | TTS_BALLOON,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		hDlg, NULL, 
		g_hInst, NULL
	);

if (!hItem || !hTooltip)
	return (HWND)NULL;
 				
/* Associate the tooltip with the item. */
toolinfo.cbSize		= sizeof(TOOLINFO);
toolinfo.hwnd		= hDlg;
toolinfo.uFlags		= TTF_IDISHWND | TTF_SUBCLASS;
toolinfo.uId		= (UINT_PTR) hItem;
toolinfo.lpszText 	= pszText;

SendMessage( hTooltip, TTM_ADDTOOL, 0, (LPARAM) &toolinfo );

return hTooltip;
}

 

 

 

Την καλώ στο WM_INITDIALOG message ενός Dialog για να προσθέσω tooltip σε μια εικόνα που περιέχει το Dialog...

 

>
switch( Message )
{
	case WM_INITDIALOG:
		TADataDlgInit( hDlg, &g_tadataDlg );

		hTooltip = DlgCreateTooltip(
				hDlg, IDBUT_TADATA_LOGO, TEXT("This is a tooltip") );

 

Χρειάζεται να το κάνω DestroyWindow( hTooltip ); πριν ή μετά το EndDialog(); ?

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...