Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Facebook Sign In with Google Sign In with OpenID

Categories

We have migrated to a new platform! Please note that you will need to reset your password to log in (your credentials are still in-tact though). Please contact lee@programmersheaven.com if you have questions.
Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Win32 Dialog Functions Locations?

Ed HallEd Hall Posts: 395Member
Time to show more of my ignorance:

I can't find this in my tutorials or on line.

Why can't I make and call a function in a Windows procedure?

Or perhaps, where can I place the function such that all the members can use it?

Specifics:

I have ID_LOAD, ID_UPDATE and ID_SAVE as cases under my WM_COMMAND switch in my strProc() procdure which opens a dialog window.

I would like to run the same routine in all three instances. Where would I put the routine?

Alternately, how would I call ID_UPDATE from within ID_SAVE?

Thanks.

Take Care,
Ed
«1

Comments

  • AsmGuru62AsmGuru62 Posts: 6,519Member
    : Time to show more of my ignorance:
    :
    : I can't find this in my tutorials or on line.
    :
    : Why can't I make and call a function in a Windows procedure?
    :
    : Or perhaps, where can I place the function such that all the members
    : can use it?
    :
    : Specifics:
    :
    : I have ID_LOAD, ID_UPDATE and ID_SAVE as cases under my WM_COMMAND
    : switch in my strProc() procdure which opens a dialog window.
    :
    : I would like to run the same routine in all three instances. Where
    : would I put the routine?
    :
    : Alternately, how would I call ID_UPDATE from within ID_SAVE?
    :
    : Thanks.
    :
    : Take Care,
    : Ed
    :
    [color=Blue]Not sure if I got your question right. You calling a function from within Windows procedure and it does not get called? That seems unlikely. Can you post some code?[/color]
  • Ed HallEd Hall Posts: 395Member
    Here's a much more detailed version:
    [code]
    BOOL CALLBACK membersDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
    switch(Message){

    case WM_INITDIALOG:{

    sNum=0;

    SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName); [blue]// I would like to have this[/blue]
    SetDlgItemText(hwnd, IDC_MI, member[sNum].MI); [blue]// in a function somewhere[/blue]
    SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName); [blue]// to be called by each[/blue]
    SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix); [blue]// case where needed[/blue]
    SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);

    return TRUE;}

    case WM_COMMAND:

    switch(LOWORD(wParam)){

    case IDC_ARTFM:{

    int i = 0;
    while (strcmp(member[i].LName, "") != 0 && i<1000)
    i++;
    if (i<1000)
    sNum=i;

    SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);
    }

    break;

    case IDC_NEXT:{

    int i = 0;
    char tempScore[10];
    if (sNum<999)
    sNum++;

    SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);
    }

    break;

    case IDC_PREV:{

    int i = 0;
    char tempScore[10];
    if (sNum>0)
    sNum--;

    SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);
    }

    break;

    case IDC_UPDATE:{

    GetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName, 20);
    GetDlgItemText(hwnd, IDC_MI, member[sNum].MI, 3);
    GetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName, 20);
    GetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix, 5);
    GetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1, 30);
    }

    [blue]// I would like to call ID_FILE_SAVE here[/blue]

    break;

    return TRUE;
    }

    LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
    switch(Message){

    case WM_COMMAND:

    switch(LOWORD(wParam)){

    case ID_FILE_EXIT:

    PostMessage(hwnd, WM_CLOSE, 0, 0);
    break;

    case ID_FILE_LOAD:{

    ifstream file;
    file.open("Tracker.sht", ios::binary);
    if (file)
    while (!file.eof()){
    file.read((char *)(&member[sNumRead]), sizeof(member[sNumRead]));
    sNumRead++;
    if (sNumRead>999)
    break;
    }
    file.close();
    }
    break;

    case ID_FILE_SAVE:{

    ofstream file;
    file.open("Tracker.sht", ios::binary);
    i=0;
    if (file)
    while (i<10){
    if (strcmp(member[i].LName, "") != 0)
    file.write((char *)(&member[i]), sizeof(member[sNum]));
    i++;
    }
    file.close();
    }
    break;
    }
    break;

    case WM_CLOSE:
    DestroyWindow(hwnd);
    break;

    case WM_DESTROY:
    PostQuitMessage(0);
    break;

    default:
    return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
    }
    [/code]
    I've tried creating a function to house the duplicate code, but I haven't found anywhere I can place it where it will compile and I can call it, including putting it under its own case, since I can't seem to call by case label either. I've tried PostMessage(), SendMessage() and PostThreadMessage(). They compile fine, but are (seemingly) ignored. I looked at SendDlgItemMessage(), but it seemed more for filling an edit control so I didn't try it. I would merely like to invoke a case from within another.

    Thanks again for all your help.

    Take Care,
    Ed
  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [color=Blue]
    Basically, you can define any functions you need at the top of the file after the includes. Put a prototypes first and then function bodies, so if a function calls another one defined later - compiler will not complain.[/color]
    [code]
    #include ...
    [color=Green]//
    // Prototypes:
    //[/color]
    int foo1 ();
    int foo2 ();
    int foo3 ();
    [color=Green]//
    // Functions code
    //[/color]
    int foo1 ()
    {
    return foo2 ();
    }

    int foo2 ()
    {
    return foo3 ();
    }

    int foo3 ()
    {
    return 1;
    }
    [/code]
    [color=Blue]Does the following work?[/color]
    : [code]:
    [color=Red]void FillControls (HWND hwnd, int index)
    {
    SetDlgItemText(hwnd, IDC_FNAME, member[index].FName);
    SetDlgItemText(hwnd, IDC_MI, member[index].MI);
    SetDlgItemText(hwnd, IDC_LNAME, member[index].LName);
    SetDlgItemText(hwnd, IDC_SUFFIX, member[index].Suffix);
    SetDlgItemText(hwnd, IDC_ADDRESS1, member[index].Add1);
    }[/color]

    : BOOL CALLBACK membersDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    : {
    : switch(Message){
    :
    : case WM_INITDIALOG:{
    :
    : sNum=0;
    :
    : [color=Green]//SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName); [blue]// I would like to have this[/blue]
    : //SetDlgItemText(hwnd, IDC_MI, member[sNum].MI); [blue]// in a function somewhere[/blue]
    : //SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName); [blue]// to be called by each[/blue]
    : //SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix); [blue]// case where needed[/blue]
    : //SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);[/color]
    :
    : [color=Red]FillControls (hwnd, sNum);[/color]
    : return TRUE;}
    :
    : case WM_COMMAND:
    :
    : switch(LOWORD(wParam)){
    :
    : case IDC_ARTFM:{
    :
    : int i = 0;
    : while (strcmp(member[i].LName, "") != 0 && i<1000)
    : i++;
    : if (i<1000)
    : sNum=i;
    :
    : [color=Green]//SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    : //SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    : //SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    : //SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    : //SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);[/color]
    : [color=Red]FillControls (hwnd, sNum);[/color]
    : }
    :
    : break;
    :
    : case IDC_NEXT:{
    :
    : int i = 0;
    : char tempScore[10];
    : if (sNum<999)
    : sNum++;
    :
    : [color=Green]//SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    : //SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    : //SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    : //SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    : //SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);[/color]
    : [color=Red]FillControls (hwnd, sNum);[/color]
    : }
    :
    : break;
    :
    : case IDC_PREV:{
    :
    : int i = 0;
    : char tempScore[10];
    : if (sNum>0)
    : sNum--;
    :
    : [color=Green]//SetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName);
    : //SetDlgItemText(hwnd, IDC_MI, member[sNum].MI);
    : //SetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName);
    : //SetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix);
    : //SetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1);[/color]
    : [color=Red]FillControls (hwnd, sNum);[/color]
    : }
    :
    : break;
    :
    : case IDC_UPDATE:{
    :
    : GetDlgItemText(hwnd, IDC_FNAME, member[sNum].FName, 20);
    : GetDlgItemText(hwnd, IDC_MI, member[sNum].MI, 3);
    : GetDlgItemText(hwnd, IDC_LNAME, member[sNum].LName, 20);
    : GetDlgItemText(hwnd, IDC_SUFFIX, member[sNum].Suffix, 5);
    : GetDlgItemText(hwnd, IDC_ADDRESS1, member[sNum].Add1, 30);
    : }
    :
    : [blue]// I would like to call ID_FILE_SAVE here[/blue]
    :
    : [color=Green]// So, you have two window procedures for now: main window
    : // and this dialog? I see two choices:
    : //
    : // 1. Create a function similar as I did with 'Fill Controls'
    : // for whole ID_FILE_SAVE case and call it here.
    : //
    : // 2. If the parent of this dialog is the main window
    : // handle and not NULL, then simply send WM_COMMAND message
    : // to it, like that:
    : //
    : // [b]SendMessage (GetParent (hwnd), WM_COMMAND, ID_FILE_SAVE, 0);[/b]
    : //[/color]
    : break;
    :
    : return TRUE;
    : }
    :
    : LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
    : {
    : switch(Message){
    :
    : case WM_COMMAND:
    :
    : switch(LOWORD(wParam)){
    :
    : case ID_FILE_EXIT:
    :
    : PostMessage(hwnd, WM_CLOSE, 0, 0);
    : break;
    :
    : case ID_FILE_LOAD:{
    :
    : ifstream file;
    : file.open("Tracker.sht", ios::binary);
    : if (file)
    : while (!file.eof()){
    : file.read((char *)(&member[sNumRead]), sizeof(member[sNumRead]));
    : sNumRead++;
    : if (sNumRead>999)
    : break;
    : }
    : file.close();
    : }
    : break;
    :
    : case ID_FILE_SAVE:{
    :
    : ofstream file;
    : file.open("Tracker.sht", ios::binary);
    : i=0;
    : if (file)
    : while (i<10){
    : if (strcmp(member[i].LName, "") != 0)
    : file.write((char *)(&member[i]), sizeof(member[sNum]));
    : i++;
    : }
    : file.close();
    : }
    : break;
    : }
    : break;
    :
    : case WM_CLOSE:
    : DestroyWindow(hwnd);
    : break;
    :
    : case WM_DESTROY:
    : PostQuitMessage(0);
    : break;
    :
    : default:
    : return DefWindowProc(hwnd, Message, wParam, lParam);
    : }
    : return 0;
    : }
    : [/code]:
    : I've tried creating a function to house the duplicate code, but I
    : haven't found anywhere I can place it where it will compile and I
    : can call it, including putting it under its own case, since I can't
    : seem to call by case label either. I've tried PostMessage(),
    : SendMessage() and PostThreadMessage(). They compile fine, but are
    : (seemingly) ignored. I looked at SendDlgItemMessage(), but it
    : seemed more for filling an edit control so I didn't try it. I would
    : merely like to invoke a case from within another.
    :
    : Thanks again for all your help.
    :
    : Take Care,
    : Ed
    :
  • Ed HallEd Hall Posts: 395Member
    Thank you for pointing out the obvious ommission to me.:-)

    I wasn't supplying the handle in my call. It is working fine now. I am still curious about calling ID_FILE_UPDATE from ID_FILE_SAVE, though.

    Additionally, to compare strings, strcmp() must be used, while integers can be compared with ==, but is there a way to compare full members of a struct? i.e.
    [code]
    struct members{
    int a, b, c;
    char charA[15], charB[12], charC[23];
    };

    members member[10];
    [/code]

    To compare elements I can use the == and strcmp():

    [code]
    if (member[3].a == member[7].a)
    do this...;

    if (strcmp(member[3].charA, member[7].charA) = 0)
    do that...;
    [/code]

    But, how do I compare member[3] to member[7]?

    Thanks again for all the help.

    Take Care,
    Ed


  • BitByBit_ThorBitByBit_Thor Posts: 2,444Member
    : Thank you for pointing out the obvious ommission to me.:-)
    :
    : I wasn't supplying the handle in my call. It is working fine now.
    : I am still curious about calling ID_FILE_UPDATE from ID_FILE_SAVE,
    : though.
    :
    : Additionally, to compare strings, strcmp() must be used, while
    : integers can be compared with ==, but is there a way to compare full
    : members of a struct? i.e.
    : [code]:
    : struct members{
    : int a, b, c;
    : char charA[15], charB[12], charC[23];
    : };
    :
    : members member[10];
    : [/code]:
    :
    : To compare elements I can use the == and strcmp():
    :
    : [code]:
    : if (member[3].a == member[7].a)
    : do this...;
    :
    : if (strcmp(member[3].charA, member[7].charA) = 0)
    : do that...;
    : [/code]:
    :
    : But, how do I compare member[3] to member[7]?
    :
    : Thanks again for all the help.
    :
    : Take Care,
    : Ed
    :
    :

    If C++ is available to you (which it probably is, as seen by the omission of struct in your definition of member[]), you could overload operator== to compare two struct members. Or the C compatible approach: a function such as strcmp; membercmp perhaps? :P
    I like the operator approach myself :)
    You could make it global, or include it into the definition of structure members (atleast I'm pretty sure you can).
    Either way, the home-brew function would have to check each member. You could perhaps also check each byte of the structure, but that's probably less neat (and more tricky with zero terminated strings) than per-member checking.

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • Ed HallEd Hall Posts: 395Member
    Thanks Richard,

    I ended up opting for a different approach after some extra thought - I created a flag and added a flag set line to all the edit and check controls. It doesn't actually mean that the data was changed, but it catches any potential change and allows a save, if desired.

    Thank you again for the help.

    Take Care,
    Ed


  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [color=Blue]Structures can be compared with a memcmp() function:[/color]
    [code]
    if (memcmp (&members [3], &members [7], sizeof (members [0])) == 0)
    {
    // structures are equal
    }
    [/code]
  • LundinLundin Posts: 3,711Member
    : [color=Blue]Structures can be compared with a memcmp()
    : function:[/color]
    : [code]:
    : if (memcmp (&members [3], &members [7], sizeof (members [0])) == 0)
    : {
    : // structures are equal
    : }
    : [/code]:


    No you can't do like that, acording to ISO C/C++, a struct/union may have padding bytes at any location.

    You actually use that kind of algorithm commonly in the preprocessor when you want to ensure that padding is disabled:

    [code]#if (sizeof(my_struct.member1) + sizeof(mystruct.member2) + ... ) != sizeof(my_struct)

    #error "Struct padding detected."

    #endif

    [/code]
  • AsmGuru62AsmGuru62 Posts: 6,519Member
    : : [color=Blue]Structures can be compared with a memcmp()
    : : function:[/color]
    : : [code]: :
    : : if (memcmp (&members [3], &members [7], sizeof (members [0])) == 0)
    : : {
    : : // structures are equal
    : : }
    : : [/code]: :
    :
    :
    : No you can't do like that, acording to ISO C/C++, a struct/union may
    : have padding bytes at any location.
    :
    : You actually use that kind of algorithm commonly in the preprocessor
    : when you want to ensure that padding is disabled:
    :
    : [code]: #if (sizeof(my_struct.member1) + sizeof(mystruct.member2) + ... ) != sizeof(my_struct)
    :
    : #error "Struct padding detected."
    :
    : #endif
    :
    : [/code]:
    :
    [color=Blue]hmmm... That is correct - I forgot about padding. I usually design my structures so they do not have padding ever. Still, compare structures member by member is time and code consuming. To protect against padding irregularity I can suggest before filling the structure with data - reset all members to zero with memset() - then fill the members.

    This will not work if structure has pointers to other objects, like strings. Strings may be equal, but pointers will be different. In such case to compare you need to do it member by member.[/color]
  • BitByBit_ThorBitByBit_Thor Posts: 2,444Member
    : This will not work if structure has pointers to other objects, like
    : strings. Strings may be equal, but pointers will be different. In
    : such case to compare you need to do it member by member.

    If we're talking about strings, also consider the zero-terminated character arrays. Comparing them is similar to the padding-bytes problem. If you memset then it'll work, but if you change the string a couple of times then you might get 'garbage' after the zero-termination, and they will note compare as equal, even though they are intended to be

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
«1
Sign In or Register to comment.