Thread: Simple WinAPI code problem.

  1. #16
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Pecado View Post
    Since the thread was continued, I'll throw a question:

    I have a main dialog(dlg1), and a dialog that pops up after pressing a button in the main one (dlg2).
    dlg2 has the DS_CONTROL in the resource.
    But whenever I press cancel in dlg2, it closes both dlg1 and dlg2, and I want to close only dlg2.
    I tried to define a different hwnd but it doesn't seem to work. Any ideas?

    By the way, in IDCANCEL I use "EndDialog(hwnd, IDCANCEL);".
    Make the sub-dialog return 1 when you close it.

    Code:
    case ID_CANCEL :
       EndDialog(hwnd, 0);
       return 1;
    case ...
    BTW... windows doesn't like case statements with break in them. You should always use return as shown.

  2. #17
    Registered User Pecado's Avatar
    Join Date
    Sep 2010
    Posts
    34
    Well I've tried doing it as you told me, but strangely it keeps closing both main and seconday dialogs, here is how it's going:

    Code:
    //PRINCIPAL DLG
    
               case IDCANCEL:
                    EndDialog(hwnd, IDCANCEL);
    // tried putting return 0; and return 1; here but still...
    Code:
    //SECONDARY DLG
    
               case IDCANCEL:
                    EndDialog(hwnd, 0);
                    return 1;

  3. #18
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Are all the other cases still using break instead of return?

    It would seem the ID_CANCEL message from the second dialog is propogating into the message queue of the first.

    Usually returning TRUE stops this... have you tried returning 0 (FALSE) both times?

  4. #19
    Registered User Pecado's Avatar
    Join Date
    Sep 2010
    Posts
    34
    Sorry to have taken so long to answer xD a toolbar is giving me a hard time...

    But yes, having replaced every "break;" with a "return 1;" solved it and now it works, thanks again!

  5. #20
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Pecado View Post
    Sorry to have taken so long to answer xD a toolbar is giving me a hard time...

    But yes, having replaced every "break;" with a "return 1;" solved it and now it works, thanks again!
    That's good to hear... Congrats!

  6. #21
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by CommonTater View Post
    That's good to hear... Congrats!
    FWIW... Generally (but not universally) return 0; means "continue processing" return 1; indicates "I have handled this".

  7. #22
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    If you have modeless dialog [started with CreateDialog() as opposed to DialogBox()] you use DestroyWindow() [not EndDialog()]

    Quote Originally Posted by CommonTater View Post
    The lpTranslated flag doesn't catch bad data... it gives an indication whether the function call suceeded or not. Causes of failure would be things like an invalid window handle, an invalid dialog item number, etc. but not the content of the edit box. If you type "hello" then call GetDlgItemInt() it simply returns 0....
    It is not about failure of GetDlgItemInt() (occassions where GetLastError() returns anything but ERROR_SUCCESS)

    GetDlgItemInt() will return '0' if the edit contains '0.123456789' or 'sometext' or if the edit empty.

    How do you tell the difference between the user inputing '0' and no input?

    Quote Originally Posted by CommonTater View Post
    windows doesn't like case statements with break in them. You should always use return as shown.
    I disagree with this. Learn to code WIN32 the 'correct' way before you start taking short-cuts with the syntax.

    I would not allow any member of my dev team to write switch statements without using 'break'.

    Not returning the correct value to show you have processed the message is the issue, not the 'break' (as I pointed out in my first post).

    Using 'break' is not a problem for windows and is syntatically correct.

    You must use 'break' in some callbacks or have multiple calls to DefWinProc() (ie to close the multi message handlers like WM_COMMAND and WM_NOTIFY).

    Changing your pattern to return from any handlers is a much better option.

    Code:
    case WM_HANDLED_MSG:
        return SomeMsgHandler();
    break;
    case WM_UNHANDLED_MSG:
    //allow this one to fall thru to the default procesing
    break;
    
    return DefWinProc();
    Last edited by novacain; 12-04-2010 at 10:04 PM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  8. #23
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by novacain View Post
    It is not about failure of GetDlgItemInt() (occassions where GetLastError() returns anything but ERROR_SUCCESS)

    GetDlgItemInt() will return '0' if the edit contains '0.123456789' or 'sometext' or if the edit empty.

    How do you tell the difference between the user inputing '0' and no input?
    Ahh... now I see your point. Yes, in that case there would be no way to know.

    I disagree with this. Learn to code WIN32 the 'correct' way before you start taking short-cuts with the syntax.
    I'll pretend you didn't say that.

    I would not allow any member of my dev team to write switch statements without using 'break'.
    They should use what works best in a given situation.

    Not returning the correct value to show you have processed the message is the issue, not the 'break' (as I pointed out in my first post).
    And how do you plan to do that without using return?


    Using 'break' is not a problem for windows and is syntatically correct.
    Except when you don't want to call DefWindowProc() after having handled a message. Passing "handled" messages on to the default procedure can cause some very strange behaviour in a Windows program. Like our friend's example where closing one window resulted in the closure of the one below it.

    You must use 'break' in some callbacks or have multiple calls to DefWinProc() (ie to close the multi message handlers like WM_COMMAND and WM_NOTIFY).
    DefWindowProc() is only for unhandled messages... for example where have a case for WM_COMMAND but only handle some of the values of WPARAM... You would call DefWindowProc() as the default case for unhandled values, but you do not want to call it for values you have dealt with in your code. Hense, you want to return from the message loop immediately after each handled message. And yes, in some message loops you will have multiple calls to return DefWindowProc().

    Try some performance testing... using return in case statements can result in a significant performance boost in message intensive programs. The advantage over break is that the loop is terminated as soon as a message is handled, the system does not need to continue analysing sections of irrelevent code to find it's way out of nested switch statements like you would find for WM_COMMAND and WM_NOTIFY. Also placing your most frequent messages at the top of the loop is even faster as it cuts down on processing time spent tunneling into unnecessary switch and case statements to find them.
    Last edited by CommonTater; 12-04-2010 at 10:30 PM.

  9. #24
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Sorry if I was not clear.

    I am all for using returns in case statements (look at the example I posted, I return the result of the msg handler function directly).

    I am not in favor of ommitting the 'break', even if it is superfluous.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  10. #25
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by novacain View Post
    Sorry if I was not clear.

    I am all for using returns in case statements (look at the example I posted, I return the result of the msg handler function directly).

    I am not in favor of ommitting the 'break', even if it is superfluous.
    And on PellesC, at least, that would result in "unreachable code" errors.

  11. #26
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Yeah but no serious person uses PellesC to do anything. It is to optimization what IE6 is to web standards

  12. #27
    Registered User Pecado's Avatar
    Join Date
    Sep 2010
    Posts
    34
    Since it's still followed... I've another simple question:

    If I want to display a selected string from a Combobox, into a Static, by pressing a Button... what is missing/wrong here?:
    Code:
    char *buffer;
    
               case IDC_BUTTON:
                    buffer = SendMessage(hwnd, CB_GETCURSEL, buffer, 0);
    		SetDlgItemText(hwnd, IDC_STATIC7, buffer);
    I've noticed that at no point do I mention the IDC_COMBOBOX, but I've also tried with
    Code:
    char *buffer;
    
               case IDC_BUTTON:
                   buffer=GetDlgItemText(hwnd, IDC_COMBOBOX, buffer, TRUE);
                   SetDlgItemText(hwnd, IDC_STATIC7, buffer);
    But still not working... Any suggestions? Thanks.

  13. #28
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    So you can't put buffer in two places like that and expect it to hold both things, right? You should (first) make buffer point to somewhere reasonable, like a bunch of empty memory that you own and (second) call GetDlgItemText and don't assign the return value to buffer because the return value is just the number of characters stored. (And the fourth argument to GetDlgItemText isn't a boolean....)

  14. #29
    Registered User
    Join Date
    Oct 2010
    Posts
    5
    Quote Originally Posted by Pecado View Post
    But still not working... Any suggestions? Thanks.
    A couple of ways you can do this:
    Code:
    //assume the text will never be more than 255 chars
    TCHAR EditBuf[255];       //array of chars
    
    //read text into array
    GetDlgItemText(hwnd, IDC_YOUREDIT, EditBuf, sizeof(EditBuf));
    
    //see what's in EditBuf
    MessageBox(NULL,EditBuf,"Buffer Contents",MB_OK);
    
    -OR-
    
    //allocate buffer to explicit length of text (+1)
    TCHAR *EditBuf=NULL;      //pointer to string
    
    //first, get length of editbox string
    int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_YOUREDIT));
    
    //allocate enough memory to hold string (+1)
    HGLOBAL hgbl = GlobalAlloc(GMEM_ZEROINIT, len+1);
    
    //if allocation succeded
    if (hgbl)
    {
    //point your buffer to allocated memory
    EditBuf=(TCHAR *)GlobalLock(hgbl;  
    
    //read text into allocated memory
    GetDlgItemText(hwnd, IDC_YOUREDIT, EditBuf, len+1);
    }
    //else, if it didn't succeed
    else
       return 0;
    
    //see what's in EditBuf
    MessageBox(NULL,EditBuf,"Buffer Contents",MB_OK);
    
    //free allocated memory
    GlobalUnlock(hgbl);
    GlobalFree(hgbl);
    EditBuf=NULL;
    
    -OR-
    
    //for easier dynamic allocation 
    TCHAR *EditBuf = new char[len+1];
    
    //use buffer...
    
    //free allocated memory
    delete [] EditBuf;
    The thing to keep in mind is that, by itself, EditBuf is just a pointer to an address in memory, you have to explicitly tell the compiler to reserve a block of <size> bytes for it to point to or create the block at runtime.

    You can do this either by static allocation, as is the case with an array[] or with a dynamic allocation, at runtime.

    In either case, you need some reserved-bytes for EditBuf to point to before you can use it.
    .
    Last edited by morongo; 12-06-2010 at 02:29 PM.

  15. #30
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Pecado View Post
    Since it's still followed... I've another simple question:

    If I want to display a selected string from a Combobox, into a Static, by pressing a Button... what is missing/wrong here?:
    Code:
    char *buffer;
    
               case IDC_BUTTON:
                    buffer = SendMessage(hwnd, CB_GETCURSEL, buffer, 0);
    		SetDlgItemText(hwnd, IDC_STATIC7, buffer);
    I've noticed that at no point do I mention the IDC_COMBOBOX, but I've also tried with
    Code:
    char *buffer;
    
               case IDC_BUTTON:
                   buffer=GetDlgItemText(hwnd, IDC_COMBOBOX, buffer, TRUE);
                   SetDlgItemText(hwnd, IDC_STATIC7, buffer);
    But still not working... Any suggestions? Thanks.
    You need memorry allocated for buffer... Simply declaring a variable does not do that.
    Either use malloc or buffer[somesize];

    Code:
    // to fetch from list to static
    
    void MoveCBListText(HWND hwnd)
      {
         char Buffer[256];  
         int idx;
    
         idx = SendDlgItemMessage(hwnd, IDC_COMBOBOX,CB_GETCURSEL,0,0)
         SendDlgItemMessage(hwnd, IDC_COMBOBOX,CB_GETLBTEXT,idx,0);
         SetDlgItemText(IDC_STATIC7,Buffer);
       }
    
    // to fetch from display to static
    
    void MoveCBDispText(HWND hwnd)
       { 
          char buffer[256];
          
          GetDlgItemText(hwnd, IDC_COMBOBOX,buffer,255);
          SetDlgItemText(hwnd,IDC_STATIC7,buffer); 
        }
    Also: I see you're still putting code in switch case statements...

    See the way I defined the functions above... creating a memory buffer and creating an int... Inside a prodedure these variable are created, the work is done, and they are destroyed when the function returns. Not only do you NOT have to define all these extra variables inside your message loop, memory usage is reduced because all these extra variables do not coexist...
    Last edited by CommonTater; 12-06-2010 at 04:21 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  2. Problem using java programs within C code
    By lemania in forum Linux Programming
    Replies: 1
    Last Post: 05-08-2005, 02:02 AM
  3. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  4. Simple Code, looking for input.
    By Alien_Freak in forum C Programming
    Replies: 3
    Last Post: 03-03-2002, 11:34 AM
  5. Simple Compile Time Problem - HELP!
    By kamikazeecows in forum Windows Programming
    Replies: 2
    Last Post: 12-02-2001, 01:30 PM