[COMCTL32_WINETEST]
[reactos.git] / rostests / winetests / comctl32 / updown.c
index 433c190..859b3a0 100644 (file)
 #define EDIT_SEQ_INDEX      1
 #define UPDOWN_SEQ_INDEX    2
 
-static HWND parent_wnd, edit, updown;
+#define UPDOWN_ID           0
+#define BUDDY_ID            1
 
-static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+static HWND parent_wnd, g_edit;
 
-static const struct message create_parent_wnd_seq[] = {
-    { WM_GETMINMAXINFO, sent },
-    { WM_NCCREATE, sent },
-    { WM_NCCALCSIZE, sent|wparam, 0 },
-    { WM_CREATE, sent },
-    { WM_SHOWWINDOW, sent|wparam, 1 },
-    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
-    { WM_QUERYNEWPALETTE,   sent|optional },
-    { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
-    { WM_ACTIVATEAPP, sent|wparam, 1 },
-    { WM_NCACTIVATE, sent|wparam, 1 },
-    { WM_ACTIVATE, sent|wparam, 1 },
-    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
-    { WM_IME_NOTIFY, sent|defwinproc|optional },
-    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
-    /* Win9x adds SWP_NOZORDER below */
-    { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
-    { WM_NCCALCSIZE, sent|wparam|optional, 1 },
-    { WM_SIZE, sent },
-    { WM_MOVE, sent },
-    { 0 }
-};
+static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
 
-static const struct message add_edit_to_parent_seq[] = {
-    { WM_PARENTNOTIFY, sent|wparam, WM_CREATE },
-    { 0 }
-};
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
 
 static const struct message add_updown_with_edit_seq[] = {
     { WM_WINDOWPOSCHANGING, sent },
@@ -182,12 +159,8 @@ static const struct message test_updown_unicode_seq[] = {
     { 0 }
 };
 
-static const struct message test_updown_destroy_seq[] = {
-    { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0 },
-    { WM_WINDOWPOSCHANGING, sent},
-    { WM_WINDOWPOSCHANGED, sent},
-    { WM_DESTROY, sent},
-    { WM_NCDESTROY, sent},
+static const struct message test_updown_pos_nochange_seq[] = {
+    { WM_GETTEXT, sent|id, 0, 0, BUDDY_ID },
     { 0 }
 };
 
@@ -254,14 +227,9 @@ static HWND create_parent_window(void)
                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
 }
 
-struct subclass_info
-{
-    WNDPROC oldproc;
-};
-
 static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-    struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+    WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
     static LONG defwndproc_counter = 0;
     LRESULT ret;
     struct message msg;
@@ -273,43 +241,37 @@ static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam,
     if (defwndproc_counter) msg.flags |= defwinproc;
     msg.wParam = wParam;
     msg.lParam = lParam;
+    msg.id     = BUDDY_ID;
     add_message(sequences, EDIT_SEQ_INDEX, &msg);
 
     defwndproc_counter++;
-    ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+    ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
     defwndproc_counter--;
     return ret;
 }
 
 static HWND create_edit_control(void)
 {
-    struct subclass_info *info;
+    WNDPROC oldproc;
+    HWND hwnd;
     RECT rect;
 
-    info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
-    if (!info)
-        return NULL;
-
     GetClientRect(parent_wnd, &rect);
-    edit = CreateWindowExA(0, "EDIT", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE,
+    hwnd = CreateWindowExA(0, WC_EDITA, NULL, WS_CHILD | WS_BORDER | WS_VISIBLE,
                            0, 0, rect.right, rect.bottom,
                            parent_wnd, NULL, GetModuleHandleA(NULL), NULL);
-    if (!edit)
-    {
-        HeapFree(GetProcessHeap(), 0, info);
-        return NULL;
-    }
+    if (!hwnd) return NULL;
 
-    info->oldproc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC,
-                                            (LONG_PTR)edit_subclass_proc);
-    SetWindowLongPtrA(edit, GWLP_USERDATA, (LONG_PTR)info);
+    oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
+                                         (LONG_PTR)edit_subclass_proc);
+    SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
 
-    return edit;
+    return hwnd;
 }
 
 static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-    struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+    WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
     static LONG defwndproc_counter = 0;
     LRESULT ret;
     struct message msg;
@@ -321,46 +283,42 @@ static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
     if (defwndproc_counter) msg.flags |= defwinproc;
     msg.wParam = wParam;
     msg.lParam = lParam;
+    msg.id     = UPDOWN_ID;
     add_message(sequences, UPDOWN_SEQ_INDEX, &msg);
 
     defwndproc_counter++;
-    ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+    ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
     defwndproc_counter--;
 
     return ret;
 }
 
-static HWND create_updown_control(void)
+static HWND create_updown_control(DWORD style, HWND buddy)
 {
-    struct subclass_info *info;
+    WNDPROC oldproc;
     HWND updown;
     RECT rect;
 
-    info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
-    if (!info)
-        return NULL;
-
     GetClientRect(parent_wnd, &rect);
-    updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ALIGNRIGHT,
-                                 0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), edit,
+    updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | style,
+                                 0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), buddy,
                                  100, 0, 50);
-    if (!updown)
-    {
-        HeapFree(GetProcessHeap(), 0, info);
-        return NULL;
-    }
+    if (!updown) return NULL;
 
-    info->oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
-                                            (LONG_PTR)updown_subclass_proc);
-    SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)info);
+    oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
+                                         (LONG_PTR)updown_subclass_proc);
+    SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)oldproc);
 
     return updown;
 }
 
 static void test_updown_pos(void)
 {
+    HWND updown;
     int r;
 
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
+
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
     /* Set Range from 0 to 100 */
@@ -410,24 +368,63 @@ static void test_updown_pos(void)
     expect(1,HIWORD(r));
 
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos_seq , "test updown pos", FALSE);
+
+    DestroyWindow(updown);
+
+    /* there's no attempt to update buddy Edit if text didn't change */
+    SetWindowTextA(g_edit, "50");
+    updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
+
+    /* test sequence only on 5.8x versions */
+    r = SendMessage(updown, UDM_GETPOS32, 0, 0);
+    if (r)
+    {
+        flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+        r = SendMessage(updown, UDM_SETPOS, 0, 50);
+        expect(50,r);
+
+        ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
+                    "test updown pos, no change", FALSE);
+    }
+
+    DestroyWindow(updown);
 }
 
 static void test_updown_pos32(void)
 {
+    HWND updown;
     int r;
     int low, high;
 
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
+
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
     /* Set the position to 0 to 1000 */
     SendMessage(updown, UDM_SETRANGE32, 0 , 1000 );
 
+    low = high = -1;
     r = SendMessage(updown, UDM_GETRANGE32, (WPARAM) &low , (LPARAM) &high );
+    if (low == -1)
+    {
+        win_skip("UDM_SETRANGE32/UDM_GETRANGE32 not available\n");
+        DestroyWindow(updown);
+        return;
+    }
+
     expect(0,low);
     expect(1000,high);
 
-    /* Set position to 500, don't check return since it is unset*/
-    SendMessage(updown, UDM_SETPOS32, 0 , 500 );
+    /* Set position to 500 */
+    r = SendMessage(updown, UDM_SETPOS32, 0 , 500 );
+    if (!r)
+    {
+        win_skip("UDM_SETPOS32 and UDM_GETPOS32 need 5.80\n");
+        DestroyWindow(updown);
+        return;
+    }
+    expect(50,r);
 
     /* Since UDM_SETBUDDYINT was not set at creation bRet will always be true as a return from UDM_GETPOS32 */
 
@@ -464,30 +461,83 @@ static void test_updown_pos32(void)
     expect(1,high);
 
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos32_seq, "test updown pos32", FALSE);
+
+    DestroyWindow(updown);
+
+    /* there's no attempt to update buddy Edit if text didn't change */
+    SetWindowTextA(g_edit, "50");
+    updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+    r = SendMessage(updown, UDM_SETPOS32, 0, 50);
+    expect(50,r);
+    ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
+                "test updown pos, no change", FALSE);
+
+    DestroyWindow(updown);
 }
 
 static void test_updown_buddy(void)
 {
-    HWND buddyReturn;
+    HWND updown, buddyReturn, buddy;
+    WNDPROC proc;
+    DWORD style;
+
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
 
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
     buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
-    ok(buddyReturn == edit, "Expected edit handle\n");
+    ok(buddyReturn == g_edit, "Expected edit handle\n");
 
-    buddyReturn = (HWND)SendMessage(updown, UDM_SETBUDDY, (WPARAM) edit, 0);
-    ok(buddyReturn == edit, "Expected edit handle\n");
+    buddyReturn = (HWND)SendMessage(updown, UDM_SETBUDDY, (WPARAM) g_edit, 0);
+    ok(buddyReturn == g_edit, "Expected edit handle\n");
 
     buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
-    ok(buddyReturn == edit, "Expected edit handle\n");
+    ok(buddyReturn == g_edit, "Expected edit handle\n");
 
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_buddy_seq, "test updown buddy", TRUE);
     ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "test updown buddy_edit", FALSE);
+
+    DestroyWindow(updown);
+
+    buddy = create_edit_control();
+    proc  = (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC);
+
+    updown= create_updown_control(UDS_ALIGNRIGHT, buddy);
+    ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
+
+    style = GetWindowLongA(updown, GWL_STYLE);
+    SetWindowLongA(updown, GWL_STYLE, style | UDS_ARROWKEYS);
+    style = GetWindowLongA(updown, GWL_STYLE);
+    ok(style & UDS_ARROWKEYS, "Expected UDS_ARROWKEYS\n");
+    /* no subclass if UDS_ARROWKEYS set after creation */
+    ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
+
+    DestroyWindow(updown);
+
+    updown= create_updown_control(UDS_ALIGNRIGHT | UDS_ARROWKEYS, buddy);
+    ok(proc != (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "Subclassing expected\n");
+
+    if (pSetWindowSubclass)
+    {
+        /* updown uses subclass helpers for buddy on >5.8x systems */
+        ok(GetPropA(buddy, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
+    }
+
+    DestroyWindow(updown);
+
+    DestroyWindow(buddy);
 }
 
 static void test_updown_base(void)
 {
+    HWND updown;
     int r;
+    CHAR text[10];
+
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
 
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
@@ -520,12 +570,36 @@ static void test_updown_base(void)
     expect(10,r);
 
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_base_seq, "test updown base", FALSE);
+
+    DestroyWindow(updown);
+
+    /* switch base with buddy attached */
+    updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
+
+    r = SendMessage(updown, UDM_SETPOS, 0, 10);
+    expect(50, r);
+
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    ok(lstrcmpA(text, "10") == 0, "Expected '10', got '%s'\n", text);
+
+    r = SendMessage(updown, UDM_SETBASE, 16, 0);
+    expect(10, r);
+
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    /* FIXME: currently hex output isn't properly formatted, but for this
+       test only change from initial text matters */
+    ok(lstrcmpA(text, "10") != 0, "Expected '0x000A', got '%s'\n", text);
+
+    DestroyWindow(updown);
 }
 
 static void test_updown_unicode(void)
 {
+    HWND updown;
     int r;
 
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
+
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
     /* Set it to ANSI, don't check return as we don't know previous state */
@@ -537,6 +611,12 @@ static void test_updown_unicode(void)
     r = SendMessage(updown, UDM_SETUNICODEFORMAT, 1 , 0);
     expect(0,r);
     r = SendMessage(updown, UDM_GETUNICODEFORMAT, 0 , 0);
+    if (!r)
+    {
+        win_skip("UDM_SETUNICODEFORMAT not available\n");
+        DestroyWindow(updown);
+        return;
+    }
     expect(1,r);
 
     /* And now set it back to ANSI */
@@ -546,49 +626,161 @@ static void test_updown_unicode(void)
     expect(0,r);
 
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_unicode_seq, "test updown unicode", FALSE);
-}
 
+    DestroyWindow(updown);
+}
 
-static void test_create_updown_control(void)
+static void test_updown_create(void)
 {
     CHAR text[MAX_PATH];
-
-    parent_wnd = create_parent_window();
-    ok(parent_wnd != NULL, "Failed to create parent window!\n");
-    ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
-
-    flush_sequences(sequences, NUM_MSG_SEQUENCES);
-
-    edit = create_edit_control();
-    ok(edit != NULL, "Failed to create edit control\n");
-    ok_sequence(sequences, PARENT_SEQ_INDEX, add_edit_to_parent_seq, "add edit control to parent", FALSE);
+    HWND updown;
+    RECT r;
 
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
-    updown = create_updown_control();
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
     ok(updown != NULL, "Failed to create updown control\n");
     ok_sequence(sequences, PARENT_SEQ_INDEX, add_updown_to_parent_seq, "add updown control to parent", TRUE);
     ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "add updown control with edit", FALSE);
 
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
 
-    GetWindowTextA(edit, text, MAX_PATH);
+    GetWindowTextA(g_edit, text, MAX_PATH);
     ok(lstrlenA(text) == 0, "Expected empty string\n");
     ok_sequence(sequences, EDIT_SEQ_INDEX, get_edit_text_seq, "get edit text", FALSE);
 
-    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+    DestroyWindow(updown);
 
-    test_updown_pos();
-    test_updown_pos32();
-    test_updown_buddy();
-    test_updown_base();
-    test_updown_unicode();
+    /* create with zero width */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.right = 0;
+    GetClientRect(updown, &r);
+    ok(r.right > 0, "Expected default width, got %d\n", r.right);
+    DestroyWindow(updown);
+    /* create with really small width */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 2, 0,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.right = 0;
+    GetClientRect(updown, &r);
+    ok(r.right != 2 && r.right > 0, "Expected default width, got %d\n", r.right);
+    DestroyWindow(updown);
+    /* create with width greater than default */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 0,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.right = 0;
+    GetClientRect(updown, &r);
+    ok(r.right < 100 && r.right > 0, "Expected default width, got %d\n", r.right);
+    DestroyWindow(updown);
+    /* create with zero height, UDS_HORZ */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.bottom = 0;
+    GetClientRect(updown, &r);
+    ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
+    DestroyWindow(updown);
+    /* create with really small height, UDS_HORZ */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 2,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.bottom = 0;
+    GetClientRect(updown, &r);
+    ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
+    DestroyWindow(updown);
+    /* create with height greater than default, UDS_HORZ */
+    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 100,
+                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
+    ok(updown != NULL, "Failed to create updown control\n");
+    r.bottom = 0;
+    GetClientRect(updown, &r);
+    ok(r.bottom < 100 && r.bottom > 0, "Expected default height, got %d\n", r.bottom);
+    DestroyWindow(updown);
+}
+
+static void test_UDS_SETBUDDYINT(void)
+{
+    HWND updown;
+    DWORD style, ret;
+    CHAR text[10];
+
+    /* cleanup buddy */
+    text[0] = '\0';
+    SetWindowTextA(g_edit, text);
+
+    /* creating without UDS_SETBUDDYINT */
+    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
+    /* try to set UDS_SETBUDDYINT after creation */
+    style = GetWindowLongA(updown, GWL_STYLE);
+    SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
+    style = GetWindowLongA(updown, GWL_STYLE);
+    ok(style & UDS_SETBUDDYINT, "Expected UDS_SETBUDDY to be set\n");
+    SendMessage(updown, UDM_SETPOS, 0, 20);
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    ok(lstrlenA(text) == 0, "Expected empty string\n");
+    DestroyWindow(updown);
+
+    /* creating with UDS_SETBUDDYINT */
+    updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    /* 50 is initial value here */
+    ok(lstrcmpA(text, "50") == 0, "Expected '50', got '%s'\n", text);
+    /* now remove style flag */
+    style = GetWindowLongA(updown, GWL_STYLE);
+    SetWindowLongA(updown, GWL_STYLE, style & ~UDS_SETBUDDYINT);
+    SendMessage(updown, UDM_SETPOS, 0, 20);
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    ok(lstrcmpA(text, "20") == 0, "Expected '20', got '%s'\n", text);
+    /* set edit text directly, check position */
+    strcpy(text, "10");
+    SetWindowTextA(g_edit, text);
+    ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
+    expect(10, ret);
+    strcpy(text, "11");
+    SetWindowTextA(g_edit, text);
+    ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
+    expect(11, LOWORD(ret));
+    expect(0,  HIWORD(ret));
+    /* set to invalid value */
+    strcpy(text, "21st");
+    SetWindowTextA(g_edit, text);
+    ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
+    expect(11, LOWORD(ret));
+    expect(TRUE, HIWORD(ret));
+    /* set style back */
+    style = GetWindowLongA(updown, GWL_STYLE);
+    SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
+    SendMessage(updown, UDM_SETPOS, 0, 30);
+    GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+    ok(lstrcmpA(text, "30") == 0, "Expected '30', got '%s'\n", text);
+    DestroyWindow(updown);
 }
 
 START_TEST(updown)
 {
+    HMODULE mod = GetModuleHandleA("comctl32.dll");
+
+    pSetWindowSubclass = (void*)GetProcAddress(mod, (LPSTR)410);
+
     InitCommonControls();
     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
 
-    test_create_updown_control();
+    parent_wnd = create_parent_window();
+    ok(parent_wnd != NULL, "Failed to create parent window!\n");
+    g_edit = create_edit_control();
+    ok(g_edit != NULL, "Failed to create edit control\n");
+
+    test_updown_create();
+    test_updown_pos();
+    test_updown_pos32();
+    test_updown_buddy();
+    test_updown_base();
+    test_updown_unicode();
+    test_UDS_SETBUDDYINT();
+
+    DestroyWindow(g_edit);
+    DestroyWindow(parent_wnd);
 }