What’s the point of the MoveWindow function when we already have SetWindowPos?


Commenter Phil Quirk notes via the suggestion box, "MoveWindow is just a weird function. I guess it's easier to call than SetWindowPos, but that's the only thing it seems to have going for it."

Yup, that's about right.

The MoveWindow function doesn't really do anything you couldn't already do yourself with SetWindowPos. It's just a convenience function. And it you look at it pretty closely, it's really not that big of a convenience either, saving you one parameter (hwndInsertAfter) and replacing the flag SWP_NOREDRAW with a boolean parameter.

Whoop-dee-doo.

It shouldn't take too much imagination to figure out how this situation came about. It's the same reason why you have both CreateWindow and CreateWindowEx.

Comments (36)
  1. Ken Hagan says:

    Pah! SetWindowPos() is for wusses. Real programmers use BeginDeferWindowPos(). (As far as I know, the same raison d’etre applies here, too.)

  2. asf says:

    @Ken Hagan: no, there is not point to use BeginDeferWindowPos for a single window.

    Besides, I’m pretty sure BeginDeferWindowPos has already been a topic on this blog. The only thing I want to know about *DeferWindowPos is how to "abort", as in, not calling EndDeferWindowPos but still free the memory

  3. Adam Ruth says:

    So why didn’t they call it MoveWindowEx then?

  4. Kevin says:

    Yep, legacy sucks. But shouldn’t Microsoft have removed it from the header files a long, long, long, long, long, long time ago? API deprecation isn’t a bad idea – developers are pretty reasonable and intelligent, and translating a call from and old API to a better one isn’t rocket science.

    [This assumes that all software is actively maintained and updated. Good luck getting an update to that custom 16-bit Delphi program from 1995 which your company relies on for order entry. “Hi, yeah, we’d like you to update the Delphi 1.0 runtime library so it doesn’t call MoveWindow. No, I’m not crazy. Hello?” -Raymond]
  5. configurator says:

    Disclaimer: I’m not a win32 programmer.

    Isn’t it possible somehow to keep the function in the DLL but remove it from the header file, thus not allowing new programs to compile with it (unless they define it themselves) but letting old programs continue to work?

  6. porter says:

    > Isn’t it possible somehow to keep the function in the DLL but remove it from the header file, thus not allowing new programs to compile with it

    There was a culling and rationalisation of the API on the move from win16 to win32. We don’t need random removal of APIs that still work unless their is some benefit. If it was left in for win64 then they missed the trick and will have to wait till win128 to remove it.

  7. davidlmorris says:

    Does this mean that MoveWindow calls SetWindowPos?  Assuming a HWND_NOTOPMOST move, are there any other reasons for why SetWindowPos is preferred?

    I have code (some goes back to 16 bit Windows days AFAIK) liberally sprinkled with MoveWindow.  Wondering if it is worth changing these to SetWindowPos the next time I do some refactoring as these changes would be fairly trivial make?

  8. Anonymous Coward says:

    Yes, Configurator, that is possible. It is even possible to define a compilation flag that will let you use the deprecated functions, just in case you have to use some third-party source code that you don’t have the time to delve into.

  9. configurator says:

    @porter: Why not? As far as I can tell. it wouldn’t break anything. Would it?

  10. steveg says:

    @davidlmorris: i wouldn’t bother myself; there are probably more interesting things to fiddle with. If it ain’t broke etc.

    Perhaps the h files could be changed to add advice (vs a warning): "M1234: MoveWindow is way old, dude. Thought about using SetWindowPos instead?" Perhaps not that useful for MoveWindow per se (there’s no real reason to not call it), but for other functions it might be more beneficial. Or potentially amusing. "M1235: CreateWindow? With no Ex? I pity the fool!".

  11. porter says:

    > Why not? As far as I can tell. it wouldn’t break anything. Would it?

    People recompiling older win32 applications with a later dev kit for starters, which happens when you maintain large applications for a significant lengths of time.

    The Win32 header files have macros to stop you using an API before it’s been introduced eg _WINNT, _WIN95 etc. But if an API is part of the WIN32 API, then you should be able to call it if you have a WIN32 conformant program, else what is the point of having a WIN32 spec?

  12. Anonymous says:

    Ah, in that case it’d be better if they’d redefined MoveWindow in headers as macros (as they did with CreateWindow). Something, like:

    #define MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint)

    SetWindowPos(hWnd, NULL, X, Y, nWidth, nHeight, SWP_NOZORDER | (bool)bRepaint * SWP_NOREDRAW))

  13. xiagouo ge says:

    Yep, legacy sucks. But shouldn’t Microsoft have removed it from the header files a long, long, long, long, long, long time ago? API deprecation isn’t a bad idea – developers are pretty reasonable and intelligent, and translating a call from and old API to a better one isn’t rocket science.

    [This assumes that all software is actively maintained and updated. Good luck getting an update to that custom 16-bit Delphi program from 1995 which your company relies on for order entry. “Hi, yeah, we’d like you to update the Delphi 1.0 runtime library so it doesn’t call MoveWindow. No, I’m not crazy. Hello?” -Raymond]

    Why not just remove it from the header file but still keep it in the dll. This way no new program can use it but all the old programs can still run and programmers have one less API to remember.

    [This assumes that when maintaining software, you’re willing to upgrade all your source code to the current version of the devkit. “All I want to do is add a null check to this one function (in a program we haven’t needed to change in 8 years), but now I get 852 compiler errors because functions like MoveWindow and OpenIcon have been deleted from the header file.” -Raymond]
  14. Dean Harding says:

    @xiagouo ge: way to read the comments before posting.

  15. Duke of New York says:

    "So why didn’t they call it MoveWindowEx then?"

    Because, as has been explained in other entries, some functions in the Windows API are older than the naming conventions.

  16. porter says:

    > #define MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint)

    Yes you could, but what does that buy you? The operating system still has to export and support the API even if the implementation of it is changed to be built on SetWindowPos rather than doing what it did before.

    And what happens if the message sequence generated by MoveWindow is different to that of SetWindowPos? Then you can potentially break an application purely through a recompilation.

  17. I'm Old says:

    I don’t understand why the 16bit legacy compromise in valid in 2009. I know NT doesn’t have to be the mascot for cutting edge OS research, but isn’t there a tipping point where you cut out the gangrenous legacy code.

  18. Neil says:

    Maybe Phil was confused by the quirk that MSDN only refers to the minimum 32-bit version of the API, so that there’s no way to tell that the 16-bit MoveWindow predated SetWindowPos.

  19. Karellen says:

    "else what is the point of having a WIN32 spec?"

    There is no "WIN32 spec". WIN32 is whatever Windows does.

    The MSDN Win32 API documentation is an attempt to describe what Windows does, but if there is ever a conflict between what MSDN says and what Windows does, it is Windows that is "correct" and MSDN which will (hopefully) change.

  20. someone else says:

    “Good luck getting an update to that custom 16-bit Delphi program from 1995 which your company relies on for order entry.”

    What’s this “16-bit” you’re talking about here?

  21. James Schend says:

    "I’m Old": Let’s do a quick benefits analysis of the function:

    Harm: Consumes like 20 bytes of disk space.

    Good: Enables gobs of older apps to run without modification or recompilation.

    Gee, which does Microsoft pick?

  22. Ken Hagan says:

    “@Ken Hagan: no, there is not point to use BeginDeferWindowPos for a single window.”

    I know, but I believe Win3.x actually implemented SetWindowPos as a three-liner, using the DeferWindowPos() functions. It’s therefore rather ironic that Raymond chose to use SetWindosPos as his example of a new-and-more-powerful replacement function, though perhaps not surprising, given that Raymond’s experience with Windows appears to pre-date any public release of the product.

    [It’s still true that SetWindowPos is newer and more powerful than MoveWindow. There didn’t seem to be any need to introduce the *DeferWindowPos family of functions – that would just have clouded the subject. Though perhaps commenter “I’m Old” would suggest that we should also get rid of the SetWindowPos function. -Raymond]
  23. KenW says:

    @I’m Old: I have a client still using a 16-bit Delphi app written on Win 3.1 to this date, running it on XP now. It works fine, and as he spent a *lot* of money having it written back then, and it would require a lot of changes to convert to 32-bit now (it has 16-bit integer operations, short strings, 64K limitation workarounds, etc. that would have to come out, and so forth); he sees no need to pay me or someone else to make those changes when things work fine as is. Can you explain why he should be forced to?

  24. I'm Old says:

    @James Schend

    @KenW

    A general policy of never cutting out legacy compatibility is what I’m arguing against. Anytime you hurt app compat there will always be that one piece of code that requires things to be done the ‘old’ way. So if you have such a strict policy in place, you could never change anything.

    Also, the problem it seems to me, only is valid when your position is that they /have/ to upgrade their OS while still maintaining app compat with 2 decade old code. Why cant they continue to use the older version?

  25. Ens says:

    @I’m Old

    But in this case the cost of legacy compatibility in this case is practically nothing, even at design-time, and therefore this argument of everything having to stay the same doesn’t really apply in this case.  There needs to be some justification to not have both of them.

    As for the second paragraph, it isn’t about whether they *have* to upgrade their OS.  What about a retailer who has binaries that worked fine but wants to sell to people with a modern OS? What if the application needs to be network-facing, and therefore using an old OS is potentially irresponsible?

    [Or the customer with two applications, one that requires an old OS (little Bobby’s favorite computer game) and one that requires a new one (Unreal Tournament 12: Final Battle). -Raymond]
  26. I'm Old says:

    “[Or the customer with two applications, one that requires an old OS (little Bobby’s favorite computer game) and one that requires a new one (Unreal Tournament 12: Final Battle).] -Raymond”

    Unreal tournament has nothing really to do with app compat. Given that there will always be new apps that wont run on older machines, (hardware OR software), that particular problem is always going to be there. Adding UT here just makes it a circular argument…

    In the same way how its unclear why support for a Windows version XYZ will stop in year XXXX, its unclear why leagacy code is supported till Version ABC. i.e. two seemingly random choices.

    [Unreal Tournament was just an example. I’m sorry my example confused you. Let’s try it again with no examples: Consider the customer with two applications, one which requires an old OS and one which requires a new one. -Raymond]
  27. James says:

    I’m Old, Microsoft has some desire to sell operating systems. It’s quite difficult to do that if core applications don’t work. I had a customer who simply refused to upgrade to Windows 95 for about 18 months because it wasn’t backwards compatible for a business-critical DOS application we’d written for them some years earlier.

    We’d happily have recompiled the application for them if someone had persuaded Informix to rework C-ISAM so that it’s locking worked on Windows 95 without the Novell network driver. Preferably without our customer having to pay Informix lots of money for the work. As it was, they didn’t upgrade to Windows 95 until the Novell driver version that made their application work came out.

    This was a fairly cheap application, only half a million Dollars or so. There are worse cases out there.

    There are people who appreciate the work that Raymond and those he works with do. I’m definitely one of them. Well, at least until all my favorite games run on Linux, then I may not have a reason to use Windows any more.

    Ah. Games don’t matter? Provided they are a backwards compatibility challenge for other operating systems but continue to run fine on Windows, they do.

    On the hardware side, remember the traditional job number one for an OS: isolating applications from changes in the hardware.

  28. Kevin says:

    [This assumes that when maintaining software, you’re willing to upgrade all your source code to the current version of the devkit. "All I want to do is add a null check to this one function (in a program we haven’t needed to change in 8 years), but now I get 852 compiler errors because functions like MoveWindow and OpenIcon have been deleted from the header file." -Raymond]

    Ok, instead of deleting MoveWindow from the header file, how about #ifdef’ing it to emit a warning about its deprecated status? (it’s already #ifdef’d to something like MoveWindowW anyways)

    But I get your point.

  29. Yuhong Bao says:

    Another example of this is CloseWindow and OpenIcon. Yep, these are alias for ShowWindow(…, SW_MAXIMIZE) and ShowWindow(…, SW_MINIMIZE), and is even worse than MoveWindow because the names were based on the Win3.x UI and has been misleading since Win95 because of it’s completely new UI.

  30. Ulric says:

    You can’t really argue that deleting MoveWindow from the header file was not an option, because deleting the ‘MoveTo’function from GDI (replaced by MoveToEx) was not a problem! ;-)

    But anyway, personally I love MoveWindow.  I absolutely hate these dancing bears of Microsoft APIs like SetWindowPos that take tons of parameters and a collection of confusing flags.  People end up calling these APIs forgetting flags or adding too many ones because they are not sure what they do, what’s slow/fast, what they’re supposed to ask and not ask for, and the code is hard to read.  I never bloody need to change the z-order!!

    I generally defend the Win32 API, but these types dancing bear APIs, and the ones that take structs with tons of members and bit flags  really suck.  

    we just want simple APIs that are optimal for 99% of the cases.  An API programmer will always argue they can’t accomodate all the edge cases so simple shouldn’t be done. Well, I’ve been writing windows apps since 1993, very complex applications with thousands of windows, everything from media players, MDI apps, video editing app, a vector graphic app, a large 3D CAD app, they all had toolbars, dynamic dialogs, custom menus, etc; I’ve done pretty much everything you can imagine in UI.  I’ve never really needed anything beyond MoveWindow.  

    Obviously, I have had to use the SWP cousin DeferWindow to reduce flicker, but again that was just to simple position child windows, equivalent to MoveWindow

  31. Yuhong Bao says:

    "But anyway, personally I love MoveWindow.  I absolutely hate these dancing bears of Microsoft APIs like SetWindowPos that take tons of parameters and a collection of confusing flags.  People end up calling these APIs forgetting flags or adding too many ones because they are not sure what they do, what’s slow/fast, what they’re supposed to ask and not ask for, and the code is hard to read."

    CreateProcess is IMO the worst here.

    BTW, what is the function used to open an icon on the Win95 and later desktops? I bet it is in Shell.

  32. Ken Hagan says:

    "we just want simple APIs that are optimal for 99% of the cases."

    Then write one. By your argument, it should be a one-liner, calling the dancing bear to do the work, but presenting the interface that you want for the task in hand.

    I suppose Microsoft *could* try to guess the subset that you want and implement it for you, but remember that the *main* job of the Win32 API is to expose *all* the capabilities of Windows, because if it doesn’t then those capabilities effectively don’t exist. Adding helper functions increases the API’s surface area. Isn’t it big enough already?

    Raymond’s point in this item is that some (many?) of the existing "helper functions" exist not because MS thought it would be helpful to add them, but because at some point in the past they *were* the fully general version of the feature they manipulate.

  33. Yuhong Bao says:

    "You can’t really argue that deleting MoveWindow from the header file was not an option, because deleting the ‘MoveTo’function from GDI (replaced by MoveToEx) was not a problem!"

    That was a different story altogether. MoveTo packed a POINT structure into a DWORD as the return value, which was okay back in the 16-bit days where x and y was 16-bit. When x and y was extended to 32-bit with Win32, the resulting total size of the POINT structure meant that it could no longer fit into a DWORD and back when the Win32 API was designed, there was no support for 64-bit integers like there is now.

  34. Ulric says:

    >Then write one. By your argument, it should be a one-liner

    By you argument, microsoft would never have any UI controls, image lists, DrawText, bezier curves, ect. because you can write your own wrappers that call the other lower functions anyway.  

    Microsoft’s goal was to create an attractive application dev platform.  It’s never really been about exposing the implemenation and telling people just write their own wrappers to make sense of it.

    For example, GDI is isn’t an API that’s a single uber-generic function to push a command buffer to accommodate all primitives and anything the implementation supports.  At one point someone decides what the friendly API should be, what the patterns are.

    >I suppose Microsoft *could* try to guess the subset

    It might be magic to you to know that people need to arrange child windows more anythig else, but that’s what API designers do.

    The design of the API framework on top of the implementation is not a burden, it’s the goal.  You DO have to understand how it’s used.

    The issue I was arguing against was this idea that MoveWindow should be deleted and we should just have the urber function that tries to offer every possible kind of windows placement anyone could possibly use.  

    We *know* by experience that the simple MoveWindow is a fundamental method on a window object, and it deserves to be its own.  A UI framework should make simple things easy, and hard this harder.  not hard things easy, and simple things hard, because it satisfies the implementation.

  35. Ulric says:

    That’s actually an interesting reply about MoveTo.  I’ve never used the return value.

    You had tons DWORD/WPARAM-to-POINT code to fix in the win16->win32 transition, and there were tools find them.

    My nit pick is pretty evil :)  if a very common functions like that require changing the code, it voids the yellow comment above that one couldn’t a function from the header file because clients would "get 852 compiler errors ". It happened.  Converting 16-bit apps to Win32 was major work.  moving to Win64 was also not a simple recompile.

  36. carlso says:

    I’m Old> "I don’t understand why the 16bit legacy compromise in valid in 2009. I know NT doesn’t have to be the mascot for cutting edge OS research, but isn’t there a tipping point where you cut out the gangrenous legacy code."

    Well, there are some Win3.1 applications written in the early 90s that are still useful today.  I use both PCs and Macs, and I have been much more impressed (and satisfied, until recently) with Microsoft’s support for older software.  I can’t run any of my older Mac software on the latest Mac OS X release which makes the latest release less useful to me than the previous one.

    I recently bought a new PC running Vista 64-bit and I was disappointed to find that it refused to allow some older 16-bit software to run (which ran fine on Windows XP 32-bit).  Why is this important?  Because after spending over a grand on a new computer, I then had to deal with a 5-year-old throwing a crying fit because he could no longer play the Win3.1-based Putt-Putt Saves The Zoo or Pajama Sam games.  So, now I have to keep that older XP computer around just to play those games.  I guess I could set up Virtual PC to run an older OS under Vista, but it sure would’ve been nice to have the ability to run these older games built-in.

    Unless support for older software is really creating a problem for newer development, why would you bother removing it?  Just for the sake of a feeling of internal cleanliness to developers?  That’s crazy.  If you remove support for existing software, you decrease the value of your operating system.  And, shouldn’t you be spending your time adding value, rather than decreasing it?  One of the impressive things about Raymond is that he’s always understood this.

Comments are closed.

Skip to main content