|
I'm trying to display a dialog box with two tabs. When the dialog displays it shows the tab control and the child dialog for the first tab ok. When I click on the second tab the child dialog disappears but the new child dialog does not appear. Clicking on the first tab again has no effect. So the initial display is ok but clicking on a tab causes the tab contents to disappear. The code i'm using is:
====== resources =====
IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 242, 156
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Tab1",IDC_TAB1,"SysTabControl32",0x0,7,24,228,99
DEFPUSHBUTTON "OK",IDOK,56,135,50,14
PUSHBUTTON "Cancel",IDCANCEL,140,135,50,14
END
IDD_DIALOG2 DIALOGEX 0, 0, 100, 50
STYLE DS_CONTROL | WS_CHILD | WS_BORDER
EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "tab 1",IDC_STATIC,24,22,17,8
CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,50,18,43,7
END
IDD_DIALOG3 DIALOGEX 0, 0, 100, 50
STYLE DS_CONTROL | WS_CHILD | WS_BORDER
EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "tab 2",IDC_STATIC,23,17,17,8
CONTROL "Check2",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,53,23,40,7
END
===== main code =====
INITCOMMONCONTROLSEX inc;
inc.dwICC = ICC_TAB_CLASSES ;
InitCommonControlsEx(&inc);
DialogBox(ghInst,MAKEINTRESOURCE(IDD_DIALOG1),hWnd,(DLGPROC)Dialog1Proc);
===== dialog proc =====
#include "stdafx.h"
#include "resource.h"
#define C_PAGES 2
typedef struct tag_tabhdr
{
HWND hTab; // tab control
int iIndex; // current tab index
BOOL bValid; // current tab status
HWND hDlg[C_PAGES]; // child windows
} TABHDR;
LRESULT CALLBACK Dialog1Proc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
extern HANDLE ghHeap;
extern HINSTANCE ghInst;
static TABHDR th;
switch(uMsg)
{
case WM_INITDIALOG:
{
DWORD dw;
POINT pt;
RECT rc;
char szMsg[256];
char szStr[128];
TCITEM tci;
// add a tab for each of the child windows
th.hTab = GetDlgItem(hDlg,IDC_TAB1);
memset(&tci,0,sizeof(TCITEM));
tci.mask = TCIF_TEXT;
tci.iImage = -1;
LoadString(ghInst,IDS_DATES,szStr,sizeof(szStr));
tci.pszText = szStr;
TabCtrl_InsertItem(th.hTab,0,&tci);
LoadString(ghInst,IDS_NOTES,szStr,sizeof(szStr));
TabCtrl_InsertItem(th.hTab,1,&tci);
// set tab control display area
GetWindowRect(th.hTab,&rc);
TabCtrl_AdjustRect(th.hTab,false,&rc);
pt.x = rc.left;
pt.y = rc.top;
ScreenToClient(hDlg,&pt);
// create the child windows
th.hDlg[0] = CreateDialog(ghInst,MAKEINTRESOURCE(IDD_DIALOG2),hDlg,(DLGPROC)PersonDatesProc);
MoveWindow(th.hDlg[0],pt.x,pt.y,rc.right-rc.left,rc.bottom-rc.top,false);
ShowWindow(th.hDlg[0],SW_HIDE);
th.hDlg[1] = CreateDialog(ghInst,MAKEINTRESOURCE(IDD_DIALOG3),hDlg,(DLGPROC)PersonNotesProc);
MoveWindow(th.hDlg[1],pt.x,pt.y,rc.right-rc.left,rc.bottom-rc.top,false);
ShowWindow(th.hDlg[1],SW_HIDE);
// simulate selection of the first tab
th.iIndex = 0;
th.bValid = TRUE;
TabCtrl_SetCurSel(th.hTab,0);
ShowWindow(th.hDlg[0],SW_SHOW);
BringWindowToTop(th.hDlg[0]);
return false;
}
break;
case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;
hDC=BeginPaint(hDlg,&ps);
EndPaint(hDlg,&ps);
}
break;
case WM_NOTIFY:
{
int iTab;
NMHDR * pnmh;
pnmh = (NMHDR *)lParam;
switch(pnmh->code)
{
case TCN_SELCHANGING:
{
// validate the tab page
iTab = TabCtrl_GetCurSel((HWND)pnmh->hwndFrom);
SendMessage(th.hDlg[iTab],UM_VALIDATE,(WPARAM)&th.bValid,0);
// return zero to allow tab to change, non-zero to prevent it
if(th.bValid)
return 0;
else
return 1;
}
break;
case TCN_SELCHANGE:
{
if(th.bValid)
{
ShowWindow(th.hDlg[th.iIndex],SW_HIDE);
th.iIndex = TabCtrl_GetCurSel((HWND)pnmh->hwndFrom);
ShowWindow(th.hDlg[th.iIndex],SW_SHOW);
BringWindowToTop(th.hDlg[th.iIndex]);
}
}
break;
}
}
break;
case WM_COMMAND:
{
HWND hCtl;
WORD wID;
WORD wCmd;
wID = LOWORD(wParam);
wCmd = HIWORD(wParam);
hCtl = (HWND)(UINT)lParam;
switch(wID)
{
case IDOK:
{
int iTab;
int iTabs = C_PAGES;
// destroy child windows
for (iTab=0;iTab
|
|
|
|
|
Shouldn't the dialog templates have the WS_VISIBLE style?
|
|
|
|
|
I would like to get the type of control (Combobox, Button etc.) at runtime by the CtrlId to use it in a loop of all controls of a Dialog.
Is there a possibility?
I tried for example
pWnd->GetDlgItem(pWnd->GetDlgCtrlID());
CRuntimeClass *RuntimeClass;
RuntimeClass = pWnd->GetRuntimeClass();
But the Return of GetRuntimeClass was always "CTempWnd"
Does anyone know a solution. I think it must be simple if you know it.
Thanks.
|
|
|
|
|
MarcoNedwig wrote:
pWnd->GetDlgItem(pWnd->GetDlgCtrlID());
That's... weird
Use:
TCHAR szClassName[200];
::GetClassName(GetDlgItem(IDC_OF_CONTROL)->m_hWnd,
szClassName, 200);
rechi
|
|
|
|
|
int GetClassName(
HWND hWnd, // handle of window
LPTSTR lpClassName, // address of buffer for class name
int nMaxCount // size of buffer, in characters
);
pWnd->GetDlgItem(pWnd->GetDlgCtrlID());
::GetClassName( pWnd->GetSafeHwnd(), sClassName.GetBuffer(64), 64);
sClassName.ReleaseBuffer();
sClassName == "EDIT", "LIST", "BUTTON" etc
|
|
|
|
|
What if the window does not belong to your application?
Suppose I only have a Handle to another Window running on the system, how do you GetDlgItem for such a situation?
Thanks,
Jim ô¿ô
|
|
|
|
|
I'd like to pass a string from an app to another using a user-defined message and SendMessage I'm receving the message but when i typecast wParam, I do not get my string but "IIIIIIIII...III" even if types and memory address match in both application when debugging.
What's wrong ?
~RaGE();
|
|
|
|
|
You can not pass pointers from one process (that is Adress Spece) to another.
You can pass them from thread to thread, but not from app to app.
The memory has a different use in the other address space.
Insted, you have to use e.g. the clipboard, a memory mapped file, or (I am not sure) GlobalAlloc might work.
My opinions may have changed, but not the fact that I am right.
|
|
|
|
|
Typecast as
CString* pString = (CString*)l; // l is the lParam value
|
|
|
|
|
jhwurmbach is basically right:
The adress space is different between processes (i.e. the same virtual address refers to different physical locations, and you might not even have access rights to that location)
A typical solution would be a memory mapped file (relatively easy to create, yet quite flexible).
Another option is a WM_COPYDATA message. You will receive a copy of the data (but this is valid only while the message is processed, so create your own copy on the client side)
for a CString:
Sender:
CString myString = ...
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.cbSize = (myString.GetLength()+1) * sizeof(TCHAR);
cds.lpData = (LPCTSTR) myString;
::SendMessage(hwndReceiver, WM_COPYDATA, (WPARAM) hwndSender, (LPARAM) &cds); Receiver - WM_COPYDATA handler:
HWND sender = (HWND) wParam;
COPYDATASTRUCT & cds = *(COPYDATASTRUCT *)cds.lpData;
CString receivedString = (LPCTSTR) cds.lpData;
Note: this does not handle passing from UNICODE app to ASCII/MBCS app (or vice versa) correctly
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
peterchen wrote:
The adress space is different between processes (i.e. the same virtual address refers to different physical locations, and you might not even have access rights to that location)
Ok .. Did not know about that ... that would explain why memory address would match without containing the value. Why is this working, then :
::SendMessage(hwndReceiver, WM_MSG, (WPARAM) hwndSender, (LPARAM) "Yopyop");
and
CString receivedString = (LPCTSTR) lParam;
peterchen wrote:
A typical solution would be a memory mapped file (relatively easy to create, yet quite flexible).
Just checked MSDN (found CMemFile), it seems to be exactly what I need ni this case.
Big thanks to all of you guys !! (I should tell Chris to add a Thanks everybody between Reply and Mail so that not only the last message gets all the thanks )
~RaGE();
|
|
|
|
|
If you send that message between 2 instances of the same application, it could work because "Yopyop" will be in a fixed position (as its a string literal) in the EXE file(and memory). But you dont get the same "Yopyop" it just looks like that
|
|
|
|
|
Thank you for explaining that!
His reply left me cluless why this should work. But your explanation is great!
My opinions may have changed, but not the fact that I am right.
|
|
|
|
|
Rage wrote:
Why is this working, then?
You could be lucky
Or, if it's the same binary, you're just passing a pointer into the data segment. As EXE's are usually mapped to the same beginning address, it works most of the time.
CMemFile is not the right thing, it's just a file in "normal" memory, but not shared between processes.
Look up CreateFileMapping and MapViewOfFile in the Win32 documentation.
And I said "relatively easy" - it's just a way to share some memory between two applications. Instead of the pointer, both sides would need to agree on a common name for the mapping - it's recommended to include a GUID in the name of the mapping - and you would have to e.g. pass an offset to the actual string. if it's just about a string, use WM_COPYDATA.
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
You guys are all making this task way too difficult.
Here's the simple solution:
ATOM A = GlobalAddAtom( _T("The String that I want to send") );
SendMessage( hWnd, msg, wParam, (LPARAM)A);
// -- at the other end
TCHAR buf[255];
GlobalGetAtomName( (ATOM)lParam, buf, 255 );
GlobalDeleteAtom( (ATOM)lParam)
// you've got your string.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Peter Weyzen<br />
Staff Engineer<br />
Santa Cruz Networks
|
|
|
|
|
Can anyone please tell me that how can i define the operator << for datatype like _int64
|
|
|
|
|
Its the same as any other operator<<.
MyObj& operator<<(__int64 i64Value)
__int64 is an MS extension so that can be a problem depending on which compiler you are trying to compile on.
|
|
|
|
|
Assuming you want to emit it to an ostream (hard to tell without you telling what you want to do with it), the follwing will do.
std::ostream& operator<<(std::ostream& os, UINT64 i)
{
char sz[32];
sprintf(sz, "%I64u", i);
os << sz;
return os;
}
|
|
|
|
|
This is how I create my window:
<br />
m_hWnd=CreateWindow("STATIC",lpszName,WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS,nX,nY,nWidth,nHeight,hParent,NULL,hInstance,NULL);<br />
It's a static window with a dialog as a parent.
Now I want to add a border to it, specificaly the "sunken" effect.
<br />
CWnd* pWnd=CWnd::FromHandle(m_hWnd);<br />
pWnd->ModifyStyleEx(0,WS_EX_CLIENTEDGE);<br />
The function returns TRUE, but I don't see any border around my static window.
Is this the right way to do it? Did I make an error?
using: [VISUAL STUDIO 6.0 sp5] [WIN98/2]
|
|
|
|
|
Use pWnd->ModifyStyleEx(0,WS_EX_CLIENTEDGE, SWP_DRAWFRAME );
rechi
|
|
|
|
|
That's it tnx
using: [VISUAL STUDIO 6.0 sp5] [WIN98/2]
|
|
|
|
|
I need your help
How to embbed a simple window into dialogbox (modeless) using CreateWindowEx function?.
I really need that one
|
|
|
|
|
My questions are these;
How can I ensure that a program which creates a file is the only one allowed to access that file? And furthermore how can I make windows clean up my temporary files (in case the program crashes or something)? Taking into consideration that the program which created the file has some sort of security lock on the file.
Something clever should be said, but I don't have the time
|
|
|
|
|
1. you can't do it directly in Windows. Windows does not support file locking or access validity of any form. Only access level rights of a file are checked while accessing a file, which comes from the current user's access rights and privileges.
Probable solution:
You need to put some sort of file encryption algo so that only authorize process/program can open it to read/write data from/into the file. but one draw back there in this. anyone can corrupt the file and data will be lost beyound recovery.
2. A
tmp files can be deleted by a countom made software that looks for special file name patters and if found can take appropriate action of deletion.. this SW can be put to start during Windows startup so that by teh time PC is ready to be used all tmp files are deleted.
2. B
also tmp file names can be logged in one common file with complete path. this file can be opened by a SW during Windows startup and all entries in that file can be deleted one by one. tmp file paths will be added to this log file by various processes/programs that require peroidic/auto deletion of log files.
techi !!
|
|
|
|
|
BhaskarBora wrote:
1. you can't do it directly in Windows. Windows does not support file locking or access validity of any form. Only access level rights of a file are checked while accessing a file, which comes from the current user's access rights and privileges.
What rubbish. See the dwShareMode param of CreateFile().
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/createfile.asp[^]
2. This is trying to clean up after the fact. Far better to prevent the problem in the first place.
Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
|
|
|
|
|