Quote: "It's not something I can control... I don't think there's a single dialog box that won't freeze the program..."
That is correct, however with a little bit of magic and a couple of hours of coding one can work around this. Behold:
#constant DLL_KERNEL32 1
` Get foreground window handle
load dll "user32.dll", 1
handle = call dll(1, "GetForegroundWindow")
delete dll 1
` Make some memory and zero-set it
lpcc = make memory(36)
lpCustColors = make memory(16*4)
fill memory lpcc, 0, 36
fill memory lpCustColors, 0, 16*4
tempPtr = lpcc
` Set COLORREF structure data
*tempPtr = 36 : inc tempPtr, 4 ` lStructSize
*tempPtr = handle ` hwndOwner
tempPtr = lpcc + 16
*tempPtr = lpCustColors : inc tempPtr, 4 ` lpCustColors
*tempPtr = 0x00000100 || 0x00000002 || 0x00000001 ` Flags
` Main loop
do
` Make buffer for function call parameters
ptr = make memory(4)
*ptr = lpcc
` Call ChooseColorA in its own thread
callPtr = CallThreadedDLLFunction("comdlg32.dll", "ChooseColorA", ptr, 4)
` Wait for call to complete
print "Waiting for user to select color..."
repeat
until CallIsComplete(callPtr)
` Set new color
tempPtr = lpcc+12
ink rgb((*tempPtr) && 0xFF, ((*tempPtr) && 0xFF00) >> 8, ((*tempPtr) && 0xFF0000) >> 16), 0
print "New color selected"
wait key
loop
function CallThreadedDLLFunction(dllName as string, funcName as string, paramPtr as dword, paramSize as dword)
local callDataPtr as dword
local codePtr as dword
local tempPtr as dword
local tempPtr2 as dword
if not dll exist(DLL_KERNEL32) then load dll "kernel32.dll", DLL_KERNEL32
dllHandle = call dll(DLL_KERNEL32, "LoadLibraryA", dllName)
procAddr = call dll(DLL_KERNEL32, "GetProcAddress", dllHandle, funcName)
kernel32Handle = call dll(DLL_KERNEL32, "GetModuleHandleA", "kernel32.dll")
freeLibrary = call dll(DLL_KERNEL32, "GetProcAddress", kernel32Handle, "FreeLibrary")
callDataPtr = make memory((paramSize/4 * 5) + 52)
codePtr = callDataPtr + 8
tempPtr = codePtr
tempPtr2 = paramPtr + paramSize - 4
for x = 1 to paramSize/4
*tempPtr = 0x68 : inc tempPtr
*tempPtr = *tempPtr2 : inc tempPtr, 4
dec tempPtr2, 4
next x
*tempPtr = 0xB8 : inc tempPtr
*tempPtr = procAddr : inc tempPtr, 4
*tempPtr = 0xD0FF : inc tempPtr, 2
*tempPtr = 0x05C7 : inc tempPtr, 2
*tempPtr = callDataPtr : inc tempPtr, 4
*tempPtr = 1 : inc tempPtr, 4
*tempPtr = 0x68 : inc tempPtr
*tempPtr = dllHandle : inc tempPtr, 4
*tempPtr = 0xB8 : inc tempPtr
*tempPtr = freeLibrary : inc tempPtr, 4
*tempPtr = 0xD0FF : inc tempPtr, 2
*tempPtr = 0xC2 || (4 << 8) : inc tempPtr, 3
*callDataPtr = 0
tempPtr = callDataPtr + 4
*tempPtr = paramPtr
call dll DLL_KERNEL32, "CreateThread", 0, 0, codePtr, 0, 0, 0
endfunction callDataPtr
function CallIsComplete(callDataPtr as dword)
if (*callDataPtr) = 0 then exitfunction 0
tempPtr = callDataPtr + 4
if (*tempPtr) then delete memory *tempPtr
delete memory callDataPtr
endfunction 1
I would have modified your code to use these functions I have written, but when I tried I couldn't seem to get it working.