1

I have a Button control wrapper class, which allows you to pass an existing handle to it, provided it is of the WC_BUTTON class. I use GetClassName() to determine this. But I have a problem, the comments in the code should help describe it:

// Initialize from existing handle
Vivify::Button::Button(HWND handle) {
    TCHAR cls[256];
    GetClassName(handle, cls, sizeof(cls));

    Alert(cls);       // MessageBox says "Button"
    Alert(WC_BUTTON); // MessageBox says "Button" also

    Str clsStr = cls;
    Str wcStr  = WC_BUTTON;

    Alert(ToStr<int>(clsStr.length())); // says "6"
    Alert(ToStr<int>(wcStr.length()));  // says "6" also

    // Problem HERE. Evaluates to false. How are they inequal??
    if (cls == WC_BUTTON) {
        SetHandle(handle); // Never gets executed
        m_id = GetDlgCtrlID(handle);
    }
}

Str is a std::wstring by the way, program is in Unicode. But both the string I get from GetClassName() and WC_BUTTON are both unicode strings, are both 6 characters long, and both equal "Button", how on earth is the line if (cls == WC_BUTTON) returning false??

Could someone explain how two seemingly exactly identical strings could be in-equal to each-other? Or how can I determine if a HWND belongs to a button/edit/etc. control?

Brandon Miller
  • 2,247
  • 8
  • 36
  • 54
  • 4
    Don't compare C strings with ==. – chris Oct 17 '12 at 23:55
  • @chris Well then how should I compare them? – Brandon Miller Oct 17 '12 at 23:56
  • 2
    If still C strings, `strcmp`. Since `vector` and `array` can act like C strings, you could also make `cls` one of those and make another, setting it's `data()` to `WC_BUTTON` and using == on those. I would say `std::string`, but you can't set its buffer directly like that. – chris Oct 17 '12 at 23:58
  • @chris Well it appears `strcmp` only works for `const char *`. So I looked into it and I see there is a Unicode version: `wcscmp`. I see it returns `0` if the strings are identical, does this mean that they only have the same length (so "this" == "that"), or does it *guarantee* that my strings are the same (so "this" != "that")? – Brandon Miller Oct 18 '12 at 00:04
  • 2
    It looks like [_tcscmp](http://msdn.microsoft.com/en-us/library/e0z9k731.aspx) is the Microsoft way to select the correct string compare function depending on whether _UNICODE or _MBCS is defined. – Blastfurnace Oct 18 '12 at 00:05
  • @BrandonMiller, It returns 0 if each character is equal. – chris Oct 18 '12 at 00:06
  • @chris Great, it works perfect. If you'd post that as an answer I'd be more than happy to accept it. – Brandon Miller Oct 18 '12 at 00:13

1 Answers1

4

You're not comparing strings, you're comparing addresses. Since the addresses are different, it returns false.

Since you need to have the function fill in the buffer, you have two main options:

a) Use C strings and _tcscmp (the TCHAR version of strcmp):

if (_tcscmp(cls, WC_BUTTON) == 0) //0 means equal

b) Use a container. std::vector and std::array let you edit the buffers, unlike std::string, but I'll show the latter.

TCHAR clsTemp[256];
GetClassName(handle, clsTemp, sizeof clsTemp / sizeof(TCHAR));
std::basic_string<TCHAR> cls = clsTemp;

if (cls == WC_BUTTON) //WC_BUTTON converted to `std::string` to compare

The constant C string version of cls can then be accessed by cls.c_str().

Note that I've changed your GetClassName call to reflect that fact that it takes the length, in characters, of the buffer, not the size in bytes. TCHAR's size might not be one, so it is necessary to divide by that.

chris
  • 60,560
  • 13
  • 143
  • 205
  • +1 Explains exactly why what I was trying to do didn't work, and gives 2 options. Also points out another flaw in my code and corrects it. Good answer. – Brandon Miller Oct 18 '12 at 00:45