|
I don’t think I have time to go back and make it all subform classes part of a big one. Yes you have the right idea in that each item corresponds to a subform. Thus a form view and a data class per subform. The checklist also has a form view class and a data class much like the subforms. Each data class has a structure to hold data as well as functions to handle the data. Such functions include passing the public data members to the private ones and vice versa (accessors and mutators). The reason why I used structs was because it was easier to transfer multiple data members at one time. Writing data to file was also easier. You just need to pass in the struct object as an argument.
Throughout the program, the data members in the checklist class gets set/reset quite often via the class object created in the main class. Each time the value changes, a call is made to the set function to set the private member to the public one.
Now when you suggested I used copy constructors in each subform, how does that make it easier to pass say 20 member variables to the constructor? Wouldn’t my overloaded constructor be very long with 20 arguments?
I don’t know if I’m confusing you but I guess my question is does my method violate the good coding practice of not having any public data members. That was what I was trying to achieve by having public structs hold variables to pass to the private one. Does that make sense to do it that way? Is there no way of avoiding having to create set/get methods for each private variable in the struct?
|
|
|
|
|
I have an exe that has to be compiled in Unicode. It links with several DLLs also compiled in Unicode. I now have to link it with another DLL that I can't compile in Unicode(it's built from 3rd party, ANSI-C source, plus some 3rd-party binaries).
When the exe link runs (msvc7) I get the messages:
LINK : warning LNK4098: defaultlib 'mfc71ud.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4098: defaultlib 'mfcs71ud.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
uafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___wargv
uafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argc
I turned on the linker switch /verbose/lib, which shows all the libs being searched. I went through the libs and removed all that were not required (i.e., that didn't generate new unresolved externs) and it didn't solve the problem. I still have the same two conflict messages and the two unresolved externs.
I think the problem must be conflicting versions of some run-time library, but I can't figure out which. (I know what argv,argc are)
Jim Scott
|
|
|
|
|
Ouch! I am getting a really bad feeling about this.
You might be better to DYNAMICALLY link with the DLL that is not Unicode enabled.
Then you can use WideCharToMultiByte before passing any strings into the non-unicode DLL. Even more power to you if the DLL does not process strings and only other data types. Just use LoadLibrary and GetProcAddress for the few functions you need from the DLL. Write a wrapper class if you have to that will give you a clean interface to the non-unicode DLL.
|
|
|
|
|
Well, passing strings between the Unicode and non-Unicode layers is exactly what I need to do. The non-U functions put their result into an array of strings whose number and lengths are not known before the functions are called. After they return, I plann to convert them from MBCS to Unicode.
Dynamically loading the non-U dll is an idea which I hadn't thought of (haven't had to do it for years, maybe not since the Win3.1 days). That will complicate the passing of strings between the two DLLS, though, since mem will be allocated in one dll and freed in another. Acutally I have to do this anyway; don't know if the dynamic load affects this issue.
Two other possibilities occur to me:
1. Create a console app out of the non-Unicode stuff. This could be spawned by the main app and could write its results to a text file, which could then be read by the unicode app. That's really ugly, but is more or less guaranteed to work.
2. Create an out-of-process COM server out of the non-Unicode component. That may not be possible, since COM is more of less always Unicode.
Jim Scott
|
|
|
|
|
Along the lines of #1, you could make an EXE that is controlled by the Unicode process, and use memory mapped files to communicate between the two programs. It might beat writing a file to disk. Then you can also constrain your memory allocations and frees to the 'same' process using the same memory model. The Non-U process would statically link to the Non-U DLL and write to the memory mapped file. IT sets an event or something, and the Unicode process reads that shared memory and does whatever conversions are required.
|
|
|
|
|
I was experimenting on a worker thread to do a timer which posts a message each second and the thread is created in the CView constructor
(MY APP is SDI)
class CMyView:public CView
{
//consturctor ...
public:
static UINT RunTimer(LPVOID p);
void Run();
public:
volatile BOOL m_bRunTimer;
//other stuff
};
CMyView::CMyView()
{
m_bRunTimer=TRUE;
//Initialize Stuff
AfxBeginThread(RunTimer,this); //Get A Thread To Post A Message Every Second
}
the Run Timer Function is used in This Way
/////////////////////////////////////////////////
UINT CMyView::RunTimer(LPVOID p)
{
((CMyView*)p)->Run ();
return 0;
}
void CMyView::Run ()
{
while (m_bRunTimer)
{
::Sleep (1000);
PostMessage (UWM_TIMER_SECOND);
/*Note Here that UWM_TIMER_MESSAGE IS user Defined Message*/
}
}
every thing works great till this point and the thread posts a message each second and the message handling is doin great the problem arises when the window(program) is closed then a debug assertion failure dialog box is displayed saying the when we are Posting a message we are posting a message to a window that no longer exists.
I tried adding The line m_bRunTimer=FALSE; in ~CMyView() but no change then i wrote some code in the
void CMyView::OnDestroy()
{
m_bRunTimer=FALSE;
::Sleep(4000);//Simply Added to Elapse the Time Slice of Main Thread
CView::OnDestroy();
}
After Doing i finally got safe with removing the thread and returns value i used TRACE() that my thread is safley removed and everything but i think my way of getting rid of the thread is kind of not portable and clean is there any other way that i can do this safley.
|
|
|
|
|
IMO, after signalling the thread to stop you should use WaitForSingleObject.
|
|
|
|
|
I was thinking that the problem could be solved with another safety check.
Make sure the window exists before posting the message!
if( ::IsWindow(m_hWnd) ){
PostMessage (UWM_TIMER_SECOND);
}
Note that you want to invoke the GLOBAL IsWindow and not the class-specific override, that is whyt he :: is in front of the function name.
Now, you avoid your crash, and some other issue you might not have discovered yet.
I always make sure the target window still exists before posting or sending a mesage from a different thread.
Now, if you waited on an event and sets its timeout to 1000 milliseconds, you could signal the event from your main thread, and the timer thread could exit sooner (instead of always being asleep for 1 second).
If you see WAIT_OBJECT_0 you exit the thread, otherwise, if it gets WAIT_TIMEOUT, you just post your message as normal. This way, your main app would not necessarily need to wait 4 seconds, it could exit immediately.
Also, a s the other person suggests, you can wait on the timer thread handle in the main thread to know when the timer thread was done.
|
|
|
|
|
Hello,
I am not sure how this works I am just beginning to learn this.
A and B are objects of the same class named TestClass
in my main i have:
...
if (A != B)
...
.cpp file has the definitions:
this class has one data member:
char* m_Str
//comparison operator !=
bool MGString::operator!=(const char* Src) const
{
bool value;
value = Compare(Src,m_Sensitive);
return value;
}
//compare function
int MGString::Compare(const char* Src, bool m_Sensitive) const
{
int result;
if (! m_Sensitive)
{
result = strcmp(m_Str,Src);
}
else
{
result = strncmp(m_Str,Src,strlen(lino));
}
if (result !=0)
return false;
else
return true;
}
//conversion operator
MGString::operator const char*()
{
return m_Str;
}
this will not compile because strlen can not accept an argument (m_Str) of type TestClass it needs a char*.
I am guessing that the way I have it set up now my conversion operator returns type char* for the data memeber m_Str for object B. However the m_Str for object A is still of type TestClass so in main when the conversion operator is called for B i think it returns a convertred value for m_Str from TestClass to char*. How do I fix this?
thanks,
Lino
|
|
|
|
|
bool operator!=(const TestClass& s1, const TestClass& s2)
{
return Compare(s1.m_Str, s2.m_Str);
}
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
can u elaborate? why is this not a class member?
and i do want to use a conversion operator...are u telling that it would be incorrect of me to use a conversion operator?
can u show me how to use the conversion operator?
thanks,
Lino
|
|
|
|
|
lino_i wrote:
can u elaborate? why is this not a class member?
That was just an example. You could also make it a member, like:
class TestClass
{
operator LPCTSTR() const
{
return m_Str;
}
bool operator!=(TestClass& s1) const
{
return Compare(m_Str, s1.m_Str);
}
};
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
thanks for your patience...
again i am a beginner at all of this but...
looking at this again why do i even need a conversion operator if m_Str is declared a char* private data member when i build my class.
why doesn't this line of code:
if (A != B) call:
bool operator!=(TestClass& sl) const
{
return Compare(m_Str, sl.m_Str);
}
what's the point of the conversion operator?
and in your scenario above what is actually getting converted (the data member of which object?)
thanks,
Lino
|
|
|
|
|
lino_i wrote:
why doesn't this line of code:
if (A != B) call:
bool operator!=(TestClass& sl) const
{
return Compare(m_Str, sl.m_Str);
}
This works fine for me:
class TestClass
{
char *m_Str;
bool Compare(const char *str1, const char *str2) const
{
return (strcmp(str1, str2) == 0);
}
public:
TestClass(){}
~TestClass(){}
operator LPCTSTR() const
{
return m_Str;
}
bool operator!=(TestClass& s1) const
{
return Compare(m_Str, s1.m_Str);
}
}; lino_i wrote:
what's the point of the conversion operator?
If you needed to call a function or method that knew nothing about a TestClass object, but it did understand what a const char* was, it would be used in that context.
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
you have a conversion operator as well...why is it necessary? m_Str is already a pointer?
|
|
|
|
|
lino_i wrote:
why is it necessary?
I didn't say that it was. I was just showing you how to implement one. If there is never a need for users of your class to access m_Str , it can be removed. However, if you did want users of your class to be able to access m_Str , it would be needed. In your case, it would not be considered a "conversion" operator, but simply an "access" operator.
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
There is lots of stuff around on skinning dialogs and dialog controls, but has anyone done anything with skinned CPropertySheet and skinned CPropertyPage ???
|
|
|
|
|
Hello,
I have a function that calls a compare function which does a simple strcmp() comparison. Then in this function I return to the calling function the value of result.
this is my compare function:
bool m_Sensitive = false;
int result;
char lino[] = "value";
if (! m_Sensitive)
{
result = strcmp(lino,Src);
}
else
{
result = strncmp(lino,Src,strlen(lino));
}
return result;
Back in the calling function which returns a bool I need to analyze the return value.
I have tried
if (return !=0)
return false;
else
return true;
this is not working any thoughts?
thanks,
Lino
|
|
|
|
|
return m_Sensitive ? strncmp(lino, Src, strlen(lino) ) == 0 : strcmp(lino,Src)== 0 ;
returns TRUE if the strings match else FALSE
|
|
|
|
|
You've not indicated what is not working. The code snippet you've shown is syntactically correct.
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
In MS Visual C++, how do I gray out a dialog's radio button *IN CODE* as opposed to using the resource editor?
|
|
|
|
|
Call EnableWindow(FALSE) .
"Opinions are neither right nor wrong. I cannot change your opinion of me. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
Thanks David! I used the following code...
GetDlgItem(IDC_RADIO1)->EnableWindow(FALSE);
|
|
|
|
|
Like this ...
<br />
void CMyDlg::EnableField(UINT nID, BOOL bEnable)<br />
{<br />
CWnd *pWnd = GetDlgItem( nID );<br />
ASSERT( pWnd );<br />
pWnd->EnableWindow( bEnable) ;<br />
}<br />
<br />
EnableField( IDC_RADIOxxx, FALSE);
Uncomment the ShowWindow statement to re-inforce the fact that a dialog window is disabled by hiding it.
|
|
|
|
|
Thanks mtzlplyk! Useful code there!
|
|
|
|