|
I have a form with some edit boxes that do validation when they lose focus. I have an error variable (int) that keeps track of whether there was an error when the control lost focus. If there is an error it increases the ref count, and if there is no error it decreases the count. I'm having some trouble wrapping my head around how to work this logically. The system encounters several errors in keeping track. For example if I tab off the first edit and there is an error the count is increased to 1. If on the next box I enter a valid value and tab off the error count is decreased since there was no error. This has the effect of taking the ref count to 0 even though the first box still has an error. The only thing I've come up with so far is to have a boolean flag that is set when the ref is increased inside the function and if it wasn't then I shouldn't decrement it when it loses focus, but I don't really like that idea. Any ideas, links, or pushes in the right directions would be very appreciated. Here is some sample code of the KillFocus
if (VerifyCircuit ()) {
if (0 != m_nFieldError) { DelErrRef (); }
if (0 == m_nFieldError)
GetDlgItem (IDC_ERROR)->ShowWindow (SW_HIDE);
ErrorString (IDC_CIRCUIT_ERROR, FALSE);
}
else {
AddErrRef ();
ErrorString (IDC_CIRCUIT_ERROR);
GetDlgItem (IDC_ERROR)->ShowWindow (SW_SHOW);
} Sorry about the lenghty post.
- monrobot13
|
|
|
|
|
Why not validate the control when it looses focus and if there is an error use PostMessage() to put the focus back on the control and pop up a tooltip or balloon showing the error. Using MessageBox()'s to notify uses is far too in your face and requires user intervention.
Note that to get focus back to a control within KillFocus you can't use SetFocus() to SendMessage(). Hope that helps.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
Thanks for the reply, but I don't particularly want to code the program that way (keeping the user on a control until it validates). I'm not popping up message boxes to notify the user I'm simply putting a * beside the box with problems.
- Aaron
|
|
|
|
|
Hi,
I have an SDI app that uses a static splitter. One side of the splitter is a class derived from TreeView and the other side is a class from FormView. When the user clicks on a node in the Tree, I need to send information to be displayed to the other view (CFormView).
I don't know how to pass that information. The document will hold the data, I need to tell my FormView derived View to update its controls (mostly text boxes), but I can't seem to figure it out. I have been through all the Splitter and Doc/View examples on the site but I am stumped.
Thanks,
Mike
|
|
|
|
|
One way is to call:
UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL );
from the TreeView. Set pSender to the TreeView and get its CView::OnUpdate() handler to ignore calls to itself. You can also put lHint to good use.
This is likely the most MFC way to do it.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
Hi, i'm working in a Win32 app. It's based on a main file, and a class file. The main file has a window which receives events and must create different instances of the class. There is a global list, where some data is saved. When certain message arrived, the new instance of the class must search for the info previously saved in the global list. The files are:
//**Main.cpp**//
include "Main.h"
SomeFunction(PCHAR Data)
{
RecordList.push_back(Data);
....
}
//**Main.h**//
#include "CX.h"
#include <list>
using namespace std ;
typedef list<PCHAR> List;
static List RecordList;
//**CX.h**//
Class X
{
...
}
//**CX.cpp**//
VOID CX::Function()
{
List::iterator i;
PCHAR Data;
i = RecordList.begin();
Data = *i;
....
}
The compiler print error C2065 in each line where the RecordList or the iterator are used. Even in the main file.
I tried including :
#include <list>
using namespace std ;
in the CX files but this doesn't work either
Any idea?
Tnx
|
|
|
|
|
does it works if you remove the static from
static List RecordList
This space is empty.
|
|
|
|
|
Problem solved
http://www.codeguru.com/forum/showthread.php?s=ed2cedde3719d44ef58b38b453c2874b&threadid=262363&highlight=global+variable+in+classes
|
|
|
|
|
well, i just started working with MFC, i made a button, and 2 edit boxes, i cant really do anything dynamic yet so how could i make when i click the button it writes moves something from onde edit box to the other?
Compiler: VC++ 6 Enterprise
OS: Windows ME
|
|
|
|
|
make member variables of cstring for each edit box. then
when the button is clicked call
UpdateData(false);
m_strEdit1 = m_strEdit2;
UpdateData(ture);
You need to get a good book on windows control and how to use them.
This space is empty.
|
|
|
|
|
for some reason that just clears the contents of both boxes
|
|
|
|
|
i found the problem, i think you go the UpdateData()'s mixed up
you have to do
UdateData(TRUE);
m_edit1 = m_edit2;
UpdateData(FALSE);
|
|
|
|
|
Yeah! I didnt exactly remember which one did what. Any ways good that you figured it out.
This space is empty.
|
|
|
|
|
As said before, what I am tying to do is get the letters of all the CD/DVD drives on the users computer using MFC. This is what I have so far:
DWORD Drives = GetLogicalDrives();
CString FormatString;
FormatString.Format("%i",Drives);
DriveControl.SetWindowText(FormatString);
FormatString returns 61... I have no idea why it is returning 61. I am assuming that I am doing it wrong? If anyone could show me how to do this right, that would be great.
-Dev578
|
|
|
|
|
GetLogicalDrives returns a bit mask. The individual bits represent the available drive letters.
GetLogicalDrives() returned 61 on your computer. A more useful way to look at this would be in binary. i.e. 111101 (or 00000000000000000000000000111101)
Starting with the least most significant bit (the right one), we see that you:
have an A drive
have no B drive
have a C drive
have a D drive
have a E drive
have a F drive
have no drives G - Z.
In your code, you can use a bitwise AND operation to parse out the individual drives' availability.
i.e:
DWORD drives = GetLogicalDrives();
if (drives & 0x01)
// have A
if (drives & 0x02)
// have B
if (drives & 0x04)
// have C
//...
|
|
|
|
|
You should also take a look at the documentation for GetLogicalDriveStrings() and GetDriveType().
|
|
|
|
|
Try this:
<br />
DWORD dwLogicalDrives = ::GetLogicalDrives();<br />
char szDriveRoot[] = "";<br />
if(dwLogicalDrives)<br />
{<br />
for(int iCnt = 0; iCnt < 32; ++iCnt)<br />
{<br />
memset(szDriveRoot, 0, sizeof(szDriveRoot));<br />
if(dwLogicalDrives & (1 << iCnt))<br />
{<br />
sprintf(szDriveRoot, "%c:\\", iCnt + 'A');<br />
UINT uiDriveType = ::GetDriveType(szDriveRoot);<br />
switch(uiDriveType)<br />
{ <br />
case DRIVE_UNKNOWN:<br />
TRACE1(_T("%s is unknown\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_NO_ROOT_DIR:<br />
TRACE1(_T("Partition %s is no root drive\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_REMOVABLE:<br />
TRACE1(_T("Partition %s is a removable device\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_FIXED:<br />
TRACE1(_T("Partition %s is a Harddisk\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_REMOTE:<br />
TRACE1(_T("Partition %s is a network drive\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_CDROM:<br />
TRACE1(_T("Partition %s is CD-ROM\n"), szDriveRoot);<br />
break;<br />
<br />
case DRIVE_RAMDISK:<br />
TRACE1(_T("Partition %s is no RAM-Disk\n"), szDriveRoot);<br />
break;<br />
}<br />
}<br />
}<br />
Pascal
|
|
|
|
|
could someone please post a working example of
a dialog based program
that has a button you click
and it runs a thread and updates an edit box based on the number of times the thread runs. Everytime i try i get error wincore.cpp assert. as you can see if my other messages posted. Someone told me to use GetSafeHWND but i get a conversion error whe i try saying it can't convert HWND from class myclass.
an example of this would be great.
thanks a million
Win32newb
"Making windows programs worse than they already are"
|
|
|
|
|
I'm not an MFC guy at all, but I ran across this in the wincore.cpp distributed with VS.NET 2003 (line 891).
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
Looks like passing CWnd objects between threads is forbidden.
If you can post your code (or snippets), someone here might be able to tell you why it's failng.
|
|
|
|
|
please look at line 254, 267,268 on this cpp
http://rafb.net/paste/results/j1260079.html (cpp file)
also look at the header file 26 thru 29 on how i have struct threadstruct
http://rafb.net/paste/results/y3002186.html (header file)
thanks for the kind help,
tony aka win32newb
Win32newb
"Making windows programs worse than they already are"
|
|
|
|
|
Ok, I'm trying to understand some of what's going on. (I'm not a fan of mfc because it's so convoluted.)
lines 267 and 268:
CCash3mfcDlg *pdlg;
*pdlg = (CCash3mfcDlg*)CWnd::FromHandle("handle");
You definitely can't do that. First off, FromHandle is expecting an HWND, not a char *. It shouldn't even compile. Second, you're dereferencing the pointer (pdlg) and assigning a different pointer to the object pdlg points to. It's difficult to explain what that code says, because it's not valid. But looking through the rest of the function, I can't see anywhere you are using pdlg, so just remove those two lines completely. They've got several problems, and they aren't necessary for any other code.
Here's your THREADSTRUCT definition:
typedef struct THREADSTRUCT
{
CCash3mfcDlg* _this;
}THREADSTRUCT;
(You could simplify that by dropping the "typedef" and replacing the trailing "THREADSTRUCT;" with just ";". Your definition is redundant. But I don't think you should have any trouble with it.)
However, int line 254, you're setting the _this variable to an HWND value:
_param->_this = GetSafeHwnd();
That's also not allowed. An HWND and an object pointer are completely separate, relatively unrelated entities.
I'd suggest that you simplify the whole thing. Recreate your project from scratch, and only add in the bare minimum of functionality, and find the first point at which it fails. Right now, you've got a pretty big chunk of code, and that makes it harder to step through and figure out the point (or points) where you've got problems.
I'd also suggest that you change StartThread and
Ongobutton as follows:
UINT CCash3mfcDlg::StartThread(LPVOID param)
{
HWND wnd = (HWND)param;
CCash3mfcDlg * dlg = (CCash3mfcDlg*)CWnd::FromHandle(wnd);
dlg->run();
return 1;
}
void CCash3mfcDlg::Ongobutton()
{
AfxBeginThread (StartThread,GetSafeHwnd());
UpdateData(TRUE); // I actually don't know what this does, but no matter.
}
I believe that should do what you want.
|
|
|
|
|
i figured it out really simple actually
UINT CCash3mfcDlg::StartThread(LPVOID param)
{
CCash3mfcDlg *tony =static_cast<ccash3mfcdlg *="">(param);
tony->run();
return 1;
}
void CCash3mfcDlg::Ongobutton()
{
UpdateData(TRUE);
AfxBeginThread (StartThread,static_cast<lpvoid>(this));
}
in the run()
CString Tempstring;
///////////////converts the int to a string for the editbox control
Tempstring.Format( "%d", m_win ); m_winupdate.SetWindowText( Tempstring );
Anotherstring.Format( "%d", counter );
m_played.SetWindowText(Anotherstring);
Loststring.Format("%d", money);
m_lostvalue.SetWindowText(Loststring);
HOPE THIS HELPS SOMEONE ELSE IN THE FUTURE
Win32newb
"Making windows programs worse than they already are"
|
|
|
|
|
win32newb wrote:
updates an edit box based on the number of times the thread runs
I'm not exactly sure what you mean by that, but I looked at your code, and I assume you want to know how many times the thread goes through the loop. One problem I saw is that you need to stop thinking linearly with threads. You call your thread, and then the line UpdateData(TRUE); may or may not be executed before the thread...so you won't always get the same results. You should use some sort of control device, like a CSemaphore so that the Ongobutton() function waits until the thread is finished. Or another method is to have your thread update your edit box directly. I've never had assert problems with using threads...here is what I usually use if I plan on using variables from my class, otherwise I just pass NULL as my second parameter:
AfxBeginThread( StartThread, static_cast<lpvoid>(this) );
If you call your thread using this, you should have access to anything defined in the calling class, as well as your controls.
Good luck, and let me know if I was any help.
|
|
|
|
|
well i get a syntax error when i do what you stated.
i know in your example you use static_cast(this) _param is assigned this so i used it instead.
UINT CCash3mfcDlg::StartThread(LPVOID param)
{
THREADSTRUCT *ts = new THREADSTRUCT;
CCash3mfcDlg *pdlg;
pdlg = (CCash3mfcDlg*)CWnd::FromHandle(ts->_this);
pdlg->run();
//here is the time-consuming process which interacts with your dialog
return 1;
}
void CCash3mfcDlg::Ongobutton()
{
THREADSTRUCT *_param = new THREADSTRUCT;
_param->_this = GetSafeHwnd();
AfxBeginThread (StartThread,static_cast(_param)); // gives me error c2059: syntax error: '('
UpdateData(TRUE);
Win32newb
"Making windows programs worse than they already are"
|
|
|
|
|
Are you declaring your StartThread function as static in your class?
|
|
|
|