I'm sick of not being able to drag & drop my windows on the taskbar. I have to open my progs in order to get what I want. That sucks! I figure I'll write an app that'll let me do that....but how? I don't know where to start or what method to use or even how to ask the question. This normally means its out of my league but I don't care this time. Its killing me.

Just to rehash the question in case it isn't clear here goes:

Problem : open windows are grouped on the taskbar in the order we open them. these cannot me moved to one side or another,

What I want : to be able to drag said windows to the left/right of other windows

Solution : ?

Thanks (and sorry bout the lenghty post & ranting),
lackluster
Posted on 2001-12-23 12:01:09 by lackluster
oh yeah, preferably on an NT/2000/XP platform.
Posted on 2001-12-23 12:02:17 by lackluster
The taskbar is a tab control so I think you should search for a method to move the tabs on a tab control around. To make them draggable you probably need some hook..

Thomas
Posted on 2001-12-23 12:28:44 by Thomas
Implementing D&D on the explorer taskbar may be nontrivial, I' m afraid.
But possibly an app can rearrange the "window buttons" by hiding and restoring the related main windows (To hide and restore a window moves the "window button" to the right).
Posted on 2001-12-24 00:11:28 by japheth
There's a freeware program on Hotfiles, called Taskbar Organizer, that seems to do what you want. I haven't looked at it, so I don't know if it uses DD or not.

http://www.zdnet.com/downloads/stories/info/0,10615,77624,00.html

:)
Posted on 2001-12-24 06:06:53 by S/390
That prog is pretty good. I wish I knew how they did it. No DnD though ;(...... still looking into it in case anybody came across a cool tut on how to do it or something similar.

thanks
Posted on 2001-12-24 23:27:30 by lackluster
Oh well, I thought it may come with source. Just a wild guess, since I didn't play with it. They do that sometimes with freeware... :grin:
Posted on 2001-12-24 23:33:38 by S/390
nah no source, but wrote a nice email asking the author ( a complete stranger) if he wanted to give a nice christmas gift ;). hopefully he'll help out
Posted on 2001-12-24 23:36:37 by lackluster
Before i start, let me say i have consumed a vast quantitiy of beer :)

I don't wnat this to delve too far into the realms of cracking, but try this:

- go to either www,sysinternals.com or www.winternals.com, and pick up RegSpy, and run it against this app, you may pick up a few valuable clues reagarding how it works.
Posted on 2001-12-25 06:23:12 by sluggy
I played a bit with tab control messages and I succeeded in reversing the order of the items (but any order is possible)!

The code is quite simple, apart from the memory stuff.
First I read all item data (TC_ITEM stucts) into a big buffer. Secondly I delete all items. Finally, I put the items back in the reversed order.

That wasn't the hardest part. The problem was that I allocated memory for the buffer, but because the message was sent to a window from explorer.exe, the memory pointers were not valid in the memory space of explorer.
I used VirtualAllocEx to allocate a buffer in explorer's memory space, and this did work. It also meant the initialization of the TC_ITEM structs in that buffer had to be done with WriteProcessMemory, because now the memory pointers where not valid in my own program.
VirtualAllocEx is only available in NT/2000 but that shouldn't be a problem for you. I think you can use some kind of shared dll in win9x if you really need it.

Finding the tab control is a bit messy, I don't know if this method is working on all systems. I just used a spy tool (download it from
NaN's site) to get the tab window and see what it's parents are.

Thomas



.data
tShTrayWnd db "Shell_TrayWnd",0
tRebarCtrl db "ReBarWindow32",0
tTaskSwClass db "MSTaskSwWClass",0
tSysTabCtrl db "SysTabControl32",0

.code

MAX_TEXT_BUFFERSIZE equ 500

MoveTaskBarItems proc uses ebx edi esi
LOCAL tbiCount:DWORD
LOCAL hTaskBar:DWORD
LOCAL explorerPID:DWORD
LOCAL hExplorer:DWORD
LOCAL tempItem:TC_ITEM
LOCAL BytesWritten:DWORD

invoke FindWindowEx, 0, 0, addr tShTrayWnd, NULL
.IF !eax
int 3
.ENDIF

invoke FindWindowEx, eax, NULL, addr tRebarCtrl, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

invoke FindWindowEx, eax, NULL, addr tTaskSwClass, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

invoke FindWindowEx, eax, NULL, addr tSysTabCtrl, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

mov hTaskBar, eax
lea ecx, explorerPID
invoke GetWindowThreadProcessId, eax, ecx




; --- Open explorer process ---
invoke OpenProcess, PROCESS_VM_OPERATION OR PROCESS_VM_WRITE, FALSE, explorerPID
.IF !eax
int 3
.ENDIF
mov hExplorer, eax

; --- get number of items on taskbar ---
invoke SendMessage, hTaskBar, TCM_GETITEMCOUNT, 0, 0
or eax, eax
jz @no_items

mov tbiCount, eax

; --- items * (sizeof TC_ITEM) + size of text buffer ---
mov ecx, (SIZEOF TC_ITEM)+ MAX_TEXT_BUFFERSIZE
mul ecx

; --- allocate memory in memory space of explorer ---
invoke VirtualAllocEx, hExplorer, NULL, eax, MEM_COMMIT, PAGE_READWRITE

; Note: the allocated memory is an array of (TC_ITEM + TextBuffer)s.
; The textbuffer is necessary to store the texts on the items

mov edi, eax
mov esi, eax

; tempitem is copied into each item before retrieving info
mov tempItem.imask, TCIF_TEXT OR TCIF_IMAGE OR TCIF_PARAM

xor ebx, ebx
.WHILE ebx<tbiCount

; --- let eax point to the text buffer ---
mov eax, esi
add eax, SIZEOF TC_ITEM

; --- store pointer to textbuffer & size in tempItem ---
mov tempItem.pszText, eax
mov tempItem.cchTextMax, MAX_TEXT_BUFFERSIZE

; --- Write this into memory space of explorer ---
invoke WriteProcessMemory, hExplorer, esi, addr tempItem, SIZEOF TC_ITEM, \
addr BytesWritten

; --- Get item info ---
invoke SendMessage, hTaskBar, TCM_GETITEM, ebx, esi

; --- move to next item in array ---
add esi, (SIZEOF TC_ITEM)+ MAX_TEXT_BUFFERSIZE
inc ebx
.ENDW

; --- delete everything ---
invoke SendMessage, hTaskBar, TCM_DELETEALLITEMS, 0, 0

mov esi, edi

xor ebx, ebx
.WHILE ebx<tbiCount
; --- get itemcount-currentcounter-1 = new index ---
mov eax, tbiCount
dec eax
sub eax, ebx
xor eax, eax

; --- place item back ---
invoke SendMessage, hTaskBar, TCM_INSERTITEM, eax, esi

; --- move to next item in array ---
add esi, (SIZEOF TC_ITEM) + MAX_TEXT_BUFFERSIZE
inc ebx
.ENDW


; --- free memory ---
invoke VirtualFreeEx, hExplorer, edi, 0, MEM_RELEASE

@no_items:
invoke CloseHandle, hExplorer
ret
MoveTaskBarItems endp
Posted on 2001-12-25 06:23:39 by Thomas
Cool. If I were female, I'd give you a big sloppy uh.....kiss ;). Maybe if you PM me we can work something out also. Just kidding, but thanks alot :).

PS - Can you explain the int 3? Its the only thing that's confusing me:confused: .
Posted on 2001-12-25 10:33:43 by lackluster
The int 3 is nothing special, it's the breakpoint interrupt that most debuggers catch, just place some error handling code there.

Thomas
Posted on 2001-12-25 11:24:59 by Thomas
I added this to the top, by just guesing

.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib


And I got this error

LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
dragdrop.exe : fatal error LNK1120: 1 unresolved externals
_
Link error
Press any key to continue . . .

What should be on top?

Have a Merry Christmas too Thomas!

Andy
Posted on 2001-12-25 11:42:14 by andy981
andy,



.486
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

WinMain proto :DWORD, :DWORD, :DWORD, :DWORD
MainProc proto :DWORD, :DWORD, :DWORD, :DWORD
MoveTaskBarItems proto

.data
tShTrayWnd db "Shell_TrayWnd",0
tRebarCtrl db "ReBarWindow32",0
tTaskSwClass db "MSTaskSwWClass",0
tSysTabCtrl db "SysTabControl32",0
ClsName db "MovClass", 0
AppName db "Move The Whales", 0

.data?
hInstance dd ?

.code

MAX_TEXT_BUFFERSIZE equ 500

Start:

invoke GetModuleHandle, NULL
mov hInstance, eax
invoke WinMain, hInstance, NULL, NULL, SW_HIDE
invoke ExitProcess, eax

WinMain proc USES esi edi ebx ebp, hInst:HINSTANCE, hPrevInstance:HINSTANCE, Cmd:LPSTR, nShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:DWORD

mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET MainProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClsName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, NULL, addr ClsName, addr AppName, WS_VISIBLE or WS_OVERLAPPEDWINDOW, \
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL
mov hwnd, eax
.WHILE TRUE
invoke GetMessage, addr msg, NULL, 0, 0
.BREAK .IF eax == 0
invoke TranslateMessage, addr msg
invoke DispatchMessage, addr msg
.endw
mov eax, msg.wParam
ret
WinMain endp

MainProc proc USES edi esi ebx ebp, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg == WM_CLOSE
invoke PostQuitMessage, NULL
.ELSEIF uMsg == WM_LBUTTONDOWN
invoke MoveTaskBarItems
.ELSE
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF
mov eax, FALSE
ret
MainProc endp


MoveTaskBarItems proc uses ebx edi esi
LOCAL tbiCount:DWORD
LOCAL hTaskBar:DWORD
LOCAL explorerPID:DWORD
LOCAL hExplorer:DWORD
LOCAL tempItem:TC_ITEM
LOCAL BytesWritten:DWORD

invoke FindWindowEx, 0, 0, addr tShTrayWnd, NULL
.IF !eax
int 3
.ENDIF

invoke FindWindowEx, eax, NULL, addr tRebarCtrl, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

invoke FindWindowEx, eax, NULL, addr tTaskSwClass, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

invoke FindWindowEx, eax, NULL, addr tSysTabCtrl, NULL
.IF !eax
int 3 ;no taskbar tab control found?
.ENDIF

mov hTaskBar, eax
lea ecx, explorerPID
invoke GetWindowThreadProcessId, eax, ecx




; --- Open explorer process ---
invoke OpenProcess, PROCESS_VM_OPERATION OR PROCESS_VM_WRITE, FALSE, explorerPID
.IF !eax
int 3
.ENDIF
mov hExplorer, eax

; --- get number of items on taskbar ---
invoke SendMessage, hTaskBar, TCM_GETITEMCOUNT, 0, 0
or eax, eax
jz @no_items

mov tbiCount, eax

; --- items * (sizeof TC_ITEM) + size of text buffer ---
mov ecx, (SIZEOF TC_ITEM)+ MAX_TEXT_BUFFERSIZE
mul ecx

; --- allocate memory in memory space of explorer ---
invoke VirtualAllocEx, hExplorer, NULL, eax, MEM_COMMIT, PAGE_READWRITE

; Note: the allocated memory is an array of (TC_ITEM + TextBuffer)s.
; The textbuffer is necessary to store the texts on the items

mov edi, eax
mov esi, eax

; tempitem is copied into each item before retrieving info
mov tempItem.imask, TCIF_TEXT OR TCIF_IMAGE OR TCIF_PARAM

xor ebx, ebx
.WHILE ebx<tbiCount

; --- let eax point to the text buffer ---
mov eax, esi
add eax, SIZEOF TC_ITEM

; --- store pointer to textbuffer & size in tempItem ---
mov tempItem.pszText, eax
mov tempItem.cchTextMax, MAX_TEXT_BUFFERSIZE

; --- Write this into memory space of explorer ---
invoke WriteProcessMemory, hExplorer, esi, addr tempItem, SIZEOF TC_ITEM, \
addr BytesWritten

; --- Get item info ---
invoke SendMessage, hTaskBar, TCM_GETITEM, ebx, esi

; --- move to next item in array ---
add esi, (SIZEOF TC_ITEM)+ MAX_TEXT_BUFFERSIZE
inc ebx
.ENDW

; --- delete everything ---
invoke SendMessage, hTaskBar, TCM_DELETEALLITEMS, 0, 0

mov esi, edi

xor ebx, ebx
.WHILE ebx<tbiCount
; --- get itemcount-currentcounter-1 = new index ---
mov eax, tbiCount
dec eax
sub eax, ebx
xor eax, eax

; --- place item back ---
invoke SendMessage, hTaskBar, TCM_INSERTITEM, eax, esi

; --- move to next item in array ---
add esi, (SIZEOF TC_ITEM) + MAX_TEXT_BUFFERSIZE
inc ebx
.ENDW


; --- free memory ---
invoke VirtualFreeEx, hExplorer, edi, 0, MEM_RELEASE

@no_items:
invoke CloseHandle, hExplorer
ret
MoveTaskBarItems endp

end Start


cut-paste-complie
Posted on 2001-12-25 12:34:07 by lackluster
Thanks Lackluster

I got it running

And

Merry Christmas

Andy!
Posted on 2001-12-25 12:49:55 by andy981
In a recent / latest issue of PCMagazine is a
utility called "Button Boogie" which does this.
Source code is available at

www.pcmag.com/utilities

farrier
Posted on 2001-12-29 11:31:23 by farrier