Нужна вот помощь такого плана Хочу код сделать такой чтобы можно было создавать окно в отдельном потоке И например вызывать в таком виде Код (Text): int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { WNDGENERIC WndPrm; CXWndParamsOverlapped(&WndPrm, 0, 0, L"CXWndClass", L"CXWndTest", GetModuleHandle(0), 0, OWN_THREAD, 10, 10, 100, 100); CXWnd *MainWindow = new CXWnd(&WndPrm); CXWndParamsOverlapped(&WndPrm, 0, 0, L"CXWndClass1", L"CXWndTest1", GetModuleHandle(0), 0, OWN_THREAD, 10, 10, 100, 100); CXWnd *MainWindow1 = new CXWnd(&WndPrm); delete MainWindow; delete MainWindow1; return 0; } Но тут недостаток большой что мой код ожидает завершения потока с MainWindow и только потом содает новое окно Судя по тому что реализовано в VCL Application->Run() кажется что именно тут и встроено ожидание сигнального состояния для всех потоков Есть ли возможность сделать это иначе? Я уже некоторых людей затрахивал подомным вопросом - так что простите если кого напрягал - сюда запостил т к решения не нашел вот код что есть Код (Text): #ifndef __ABSTRACTH #define __ABSTRACTH #include<windows.h> typedef struct _SIZES { DWORD X; DWORD Y; DWORD Width; DWORD Height; }SIZES, *PSIZES; typedef struct _WNDGENERIC { DWORD GenStyle; DWORD ExtraStyle; DWORD ID; PWCHAR ClassName; PWCHAR WindowName; HINSTANCE Instance; HWND Parent; BOOL OwnsAThread; SIZES WndSize; }WNDGENERIC, *PWNDGENERIC; typedef enum _RSRC { RSRC_BMP = 0, RSRC_JPG = 1, RSRC_GIF = 2, RSRC_PNG = 3, RSRC_CUR = 4, RSRC_ICO = 5 }RSRC; typedef struct _WNDRESOURCE { BOOL External; //external PWCHAR Name;//resource name if external RSRC ResourceType;//resource type DWORD ResourceID;//if from resources //internal DWORD Color;//color HRGN Region;//region }WNDRESOURCE, *PWNDRESOURCE; //unifying resources class WinXResourceContainer { private: PWNDRESOURCE Rsrc; public: WinXResourceContainer(PWNDRESOURCE Rsrc); BOOL MakeOperation(/*operation*/){}; ~WinXResourceContainer(); }; #endif Код (Text): #ifndef __CXWND #define __CXWND #include"Abstract.h" #include<windows.h> #define OWN_THREAD 1 #define THIS_CONTEXT 0 class CXWnd { private: WNDGENERIC Params; MSG Msg; HANDLE WndThread; HWND WndHandle; void Destroy(); void Show(UINT Show); DWORD MessageDispatch(); friend DWORD Create(CXWnd *WndObj); friend LRESULT __stdcall CXWndProc(HWND , UINT msg, LPARAM lparam, WPARAM wparam); public: BOOL SetRegionResource(PWNDRESOURCE Rsrc); BOOL SetPosition(PSIZES Pstn); BOOL SetName(PWCHAR Name); HWND GetHWND(); HANDLE GetThreadHandle(); CXWnd(PWNDGENERIC Params); ~CXWnd(); }; void __forceinline CXWndParamsOverlapped(PWNDGENERIC Prm, DWORD ExtraStyle, DWORD ID, PWCHAR ClassName, PWCHAR WindowName, HINSTANCE Instance, HWND Parent, BOOL OwnsAThread, DWORD X, DWORD Y, DWORD H, DWORD W) { Prm->GenStyle = WS_OVERLAPPEDWINDOW; Prm->ClassName = ClassName; Prm->ExtraStyle = ExtraStyle; Prm->ID = ID; Prm->Instance = Instance; Prm->OwnsAThread = OwnsAThread; Prm->Parent = Parent; Prm->WindowName = WindowName; Prm->WndSize.X = X; Prm->WndSize.Y = Y; Prm->WndSize.Height = H; Prm->WndSize.Width = W; } #endif и реализация Код (Text): #include"CXWnd.h" #include<windows.h> LRESULT __stdcall CXWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_CREATE: { return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC dc; dc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 0; } case WM_CLOSE: { DestroyWindow(hwnd); return 0; } case WM_DESTROY: { PostMessage(hwnd, WM_QUIT, 0, 0); return 0; } } return DefWindowProc(hwnd, msg, wparam, lparam); } DWORD CXWnd::MessageDispatch() { DWORD Ret; while(TRUE) { Ret = GetMessage(&Msg, 0, 0, 0); if(Ret==-1) return -1; else if(!Ret) break; else { TranslateMessage(&Msg); DispatchMessage(&Msg); } } return (WPARAM)Msg.wParam; } void CXWnd::Show(UINT Show) { if(Params.OwnsAThread) ::ShowWindowAsync(WndHandle, Show); else ::ShowWindow(WndHandle, Show); UpdateWindow(WndHandle); } DWORD Create(CXWnd *WndObj) { WNDCLASSEXW wc; DWORD Ret; RtlZeroMemory(&wc, sizeof(wc)); wc.cbSize = sizeof(wc); wc.hInstance = WndObj->Params.Instance; wc.lpszClassName = WndObj->Params.ClassName; wc.style = CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = CXWndProc; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hIconSm = wc.hIcon; wc.hCursor = LoadCursor(0, IDC_ARROW); if(!RegisterClassEx(&wc)) return -1; WndObj->WndHandle = CreateWindowEx(WndObj->Params.ExtraStyle, WndObj->Params.ClassName, WndObj->Params.WindowName, WndObj->Params.GenStyle, WndObj->Params.WndSize.X, WndObj->Params.WndSize.Y, WndObj->Params.WndSize.Width, WndObj->Params.WndSize.Height, WndObj->Params.Parent, (HMENU)WndObj->Params.ID, WndObj->Params.Instance, 0); // think about it! if(!WndObj->WndHandle) return -1; else { WndObj->Show(SW_SHOWNORMAL); ::UpdateWindow(WndObj->WndHandle); Ret = WndObj->MessageDispatch(); } return Ret; } HWND CXWnd::GetHWND() { return WndHandle; } void CXWnd::Destroy() { if(Params.OwnsAThread) { CloseHandle(WndThread); } delete []Params.WindowName; delete []Params.ClassName; RtlZeroMemory(&Params, sizeof(Params)); } BOOL CXWnd::SetRegionResource(PWNDRESOURCE Rsrc) { return FALSE; } BOOL CXWnd::SetPosition(PSIZES Pstn) { return FALSE; } BOOL CXWnd::SetName(PWCHAR Name) { PostMessage(WndHandle, WM_SETTEXT, 0, Name); return FALSE; } HANDLE CXWnd::GetThreadHandle() { return WndThread; } CXWnd::CXWnd(PWNDGENERIC InParams) { RtlCopyMemory(&Params, InParams, sizeof WNDGENERIC); Params.WindowName = new WCHAR[lstrlenW(InParams->WindowName) + 1]; RtlCopyMemory(Params.WindowName, InParams->WindowName, (lstrlenW(InParams->WindowName) + 1) * sizeof WCHAR); Params.ClassName = new WCHAR[lstrlenW(InParams->ClassName) + 1]; RtlCopyMemory(Params.ClassName, InParams->ClassName, (lstrlenW(InParams->ClassName) + 1) * sizeof WCHAR); if(Params.OwnsAThread) { WndThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Create, this, 0, 0); if(!WndThread) return; if(WaitForSingleObject(WndThread, INFINITE)==WAIT_FAILED) return; } else Create(this); } CXWnd::~CXWnd() { Destroy(); } З Ы: понятное дело что тут все не правильно - подскажите как сделать правильно
Самодельные обёртки? Занимательно. Для запуска окна с другого потока ты должен сделать и выборку сообщений в том же потоке. Имхо.
UTeX Не так понял вопрос. А в чём проблема, если не ждать? Непонятно, что требуется получить в итоге, VCL не знаю. Если требуется создать несколько окон в отдельных потоках и подождать потом их завершения, то почему бы не создать окна, а ожидать их в отдельной функции, например: Код (Text): ... CXWnd *MainWindow1 = new CXWnd(&WndPrm); HANDLE wnds[2] = {MainWindow->WndThread, MainWindow1->WndThread}; WaitForMultipleObjects(2, wnds, TRUE, INFINITE); delete MainWindow;
Это все верно. Но просто не очень номально как мне кажется если я собираюсь создавать таким же образом например и дочерние окна. Поэтому было бы неплохо услышать еще какое-нибудь решение.
? ---- Способ не ждать: Код (Text): WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data _class db "%d_class",0 _button db "button",0 rect RECT <10,10,90,60> .data? hinst dd ? hwin dd ? count dd ? .code ThreadProc proc param:DWORD invoke WinMain,hinst,0,0,SW_SHOWDEFAULT invoke ExitThread,0 ret ThreadProc endp WndProc proc uses ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM local ps:PAINTSTRUCT mov eax,hWnd .if uMsg==WM_DESTROY invoke PostQuitMessage,0 xor eax,eax .elseif uMsg==WM_PAINT invoke BeginPaint,hWnd,addr ps mov ebx,eax invoke GetStockObject,BLACK_BRUSH invoke FillRect,ebx,addr rect,eax invoke EndPaint,hWnd,addr ps xor eax,eax .elseif uMsg==WM_COMMAND && wParam==3000 && eax==hwin inc count invoke CreateThread,0,0,offset ThreadProc,0,0,0 invoke CloseHandle,eax xor eax,eax .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam .endif ret WndProc endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local msg:MSG local hWnd:HWND local buf[32]:BYTE mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc,offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 mov eax,hInst mov wc.hInstance,eax mov wc.hbrBackground,COLOR_WINDOW mov wc.lpszMenuName,0 invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_HAND mov wc.hCursor,eax invoke wsprintf,addr buf,offset _class,count lea eax,buf mov wc.lpszClassName,eax invoke RegisterClassEx,addr wc mov eax,count .if eax==0 mov ecx,500 .else shl eax,4 mov ecx,eax .endif invoke CreateWindowEx,WS_EX_CLIENTEDGE OR WS_EX_TOPMOST OR WS_EX_TOOLWINDOW,addr buf,addr buf,WS_OVERLAPPEDWINDOW,ecx,eax,300,200,0,0,hInst,0 mov hWnd,eax invoke ShowWindow,hWnd,SW_SHOWDEFAULT invoke UpdateWindow,hWnd ; invoke SetWindowLong,hWnd,GWL_USERDATA,count .if count==0 invoke CreateWindowEx,0,addr _button,0,WS_VISIBLE OR WS_CHILD,10,80,80,20,hWnd,3000,hinst,0 mov eax,hWnd mov hwin,eax .endif .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret WinMain endp start: invoke GetModuleHandle,0 mov hinst,eax invoke WinMain,eax,0,0,SW_SHOWDEFAULT invoke ExitProcess,eax end start
kero Архив чего то битый - так что исходник не увидел - но прогу запустил - похоже это то что нужно возможно а возможно и нет Перезалий плиз куда нибудь исходник на www.everfall.com/paste например
>Архив чего то битый Не битый. Хинт: васм предпочитает качалки (ReGet, etc). Но код добавил, см. взад .
Концепт: Либо 1 цикл разбора сообщений - фильтрация msg по всем hwnd (если много процедур обработки) - но теряются потоковые сообщения с hwnd=0 (если всё-таки потоки пролеплены к окошкам, каким-то боком)! либо каждому потоку по циклу с тем же разбором по hwnd (окон больше, чем 1 на поток и для каждого своя процедура обработки) - ничего не теряется. А так вопрос - что будет то в потоках выполняться? Циклы выборки и фильтрации или просто процедуры обработки сообщений? Последнее конечно легче. На стадии инициализации создаём все потоки суспеденными и в нужный момент просто запускаем тот, что нужно, потом снова останавливаем, не уничтожая объек потока (много накладных расходов)!
asmfan это ведь и так ясно. интересно код который я привел кто-то смотрел там явно видно то что я пытаюсь сделать kero Не пойму только каким образом можно избежать создания окна в основном потоке. есть идеи? Просто если его каким то образом не зациклить то сделать не удастся?
Судя по всему это реально только в таком виде, как я и думал раньше т.е. нужно создать процедуру жидания сигнального состояния всех созданных хендлов окна
UTeX Где в твоём коде отдельные потоки в упор не пойму. Где отдельные разные процедуры обработки? Видимо не так всё ясно, как кажется.
Код (Text): DWORD Create(CXWnd *WndObj) { WNDCLASSEXW wc; DWORD Ret; RtlZeroMemory(&wc, sizeof(wc)); wc.cbSize = sizeof(wc); wc.hInstance = WndObj->Params.Instance; wc.lpszClassName = WndObj->Params.ClassName; wc.style = CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = CXWndProc; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hIconSm = wc.hIcon; wc.hCursor = LoadCursor(0, IDC_ARROW); if(!RegisterClassEx(&wc)) return -1; WndObj->WndHandle = CreateWindowEx(WndObj->Params.ExtraStyle, WndObj->Params.ClassName, WndObj->Params.WindowName, WndObj->Params.GenStyle, WndObj->Params.WndSize.X, WndObj->Params.WndSize.Y, WndObj->Params.WndSize.Width, WndObj->Params.WndSize.Height, WndObj->Params.Parent, (HMENU)WndObj->Params.ID, WndObj->Params.Instance, 0); // think about it! if(!WndObj->WndHandle) return -1; else { WndObj->Show(SW_SHOWNORMAL); ::UpdateWindow(WndObj->WndHandle); Ret = WndObj->MessageDispatch(); } return Ret; } это код потока
пока что одна - она ничего все равно не делает - не в ней суть и вообще апочему они должны быть разными? вобщем неясность для меня основная не в этом
А почему Create как friend, а не как static? Ведь работает всё-равно по указателю без прямого обращения к членам. Callback'и я бы вручную устанавливал динамически. Окна все равноправны. Ожидание внутри класса реализовано. Объектов синхронизации наружу не выведено ни эвентов ни хэндлов потоков. А так всё вроде работать будет.
Да хоть Sleep: Код (Text): .data _class db "MultiMain_%10.10lu",0 _title db "%s_%lu",0 _button db "button",0 _help db " MultiMain by kero // Exit: F12 // Create new window thread: F11, or any big button of the previous threads ",0 rect RECT <10,10,90,60> .data? hinst dd ? .code MessageLoop proc local msg:MSG .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret MessageLoop endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local hWnd:HWND local buf[32]:BYTE mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc,offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 mov eax,hInst mov wc.hInstance,eax mov wc.lpszMenuName,0 invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_HAND mov wc.hCursor,eax invoke GetTickCount push eax push eax invoke GetTickCount and eax,0ffffh pop ecx shl eax,8 mov al,cl invoke CreateSolidBrush,eax mov wc.hbrBackground,eax pop eax invoke wsprintf,addr buf,offset _class,eax lea eax,buf mov wc.lpszClassName,eax invoke RegisterClassEx,addr wc invoke CreateWindowEx,WS_EX_CLIENTEDGE OR WS_EX_TOPMOST OR WS_EX_TOOLWINDOW,addr buf,0,WS_OVERLAPPEDWINDOW,300,0,240,180,0,0,hInst,0 mov hWnd,eax invoke ShowWindow,hWnd,SW_SHOWDEFAULT invoke UpdateWindow,hWnd invoke MessageLoop push eax invoke UnregisterClass,addr buf,hInst pop eax ret WinMain endp SubProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .if uMsg==WM_DESTROY invoke DestroyWindow,hWnd xor eax,eax .else invoke GetWindowLong,hWnd,GWL_USERDATA invoke CallWindowProc,eax,hWnd,uMsg,wParam,lParam .endif ret SubProc endp ThreadProc proc param:DWORD invoke WinMain,hinst,0,0,SW_SHOWDEFAULT invoke ExitThread,0 ret ThreadProc endp WndProc proc uses ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM local ps:PAINTSTRUCT local buf[32]:BYTE mov eax,hWnd .if uMsg==WM_DESTROY invoke PostQuitMessage,0 xor eax,eax .elseif uMsg==WM_CREATE invoke CreateWindowEx,0,addr _button,0,WS_VISIBLE OR WS_CHILD, 10,80,80,24,hWnd,3000,hinst,0 invoke CreateWindowEx,0,addr _button,0,WS_VISIBLE OR WS_CHILD,110,10,40,24,hWnd,3001,hinst,0 invoke GetClassName,hWnd,addr buf,31 mov ebx,hWnd jmp @f .elseif uMsg==WM_COMMAND && wParam==3001 invoke GetClassName,hWnd,addr buf,31 invoke CreateWindowEx,WS_EX_CLIENTEDGE OR WS_EX_TOPMOST OR WS_EX_TOOLWINDOW,addr buf,0,WS_OVERLAPPEDWINDOW OR WS_VISIBLE,0,0,210,150,0,0,hinst,0 mov ebx,eax invoke SetWindowLong,ebx,GWL_WNDPROC,addr SubProc invoke SetWindowLong,ebx,GWL_USERDATA,eax @@: invoke GetWindowThreadProcessId,ebx,0 invoke wsprintf,addr buf,offset _title,addr buf,eax invoke SetWindowText,ebx,addr buf xor eax,eax .elseif uMsg==WM_COMMAND && wParam==3000 invoke CreateThread,0,0,offset ThreadProc,0,0,0 invoke CloseHandle,eax xor eax,eax .elseif uMsg==WM_PAINT invoke BeginPaint,hWnd,addr ps mov ebx,eax invoke GetStockObject,BLACK_BRUSH invoke FillRect,ebx,addr rect,eax invoke GetStockObject,WHITE_BRUSH invoke FrameRect,ebx,addr rect,eax invoke EndPaint,hWnd,addr ps xor eax,eax .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam .endif ret WndProc endp ScreenText proc uses ebx lpstr:LPSTR invoke MessageBeep,0 invoke GetDC,0 mov ebx,eax invoke lstrlen,lpstr invoke TextOut,ebx,0,0,lpstr,eax invoke ReleaseDC,0,ebx ret ScreenText endp start: invoke GetModuleHandle,0 mov hinst,eax invoke ScreenText,offset _help @0: invoke Sleep,50 invoke GetKeyState,VK_F11 and eax,8000h jz @1 invoke InvalidateRect,0,0,1 @2: invoke Sleep,10 ; анти дребезг контактов invoke GetKeyState,VK_F11 and eax,8000h jnz @2 invoke CreateThread,0,0,offset ThreadProc,0,0,0 invoke CloseHandle,eax @1: invoke GetKeyState,VK_F12 and eax,8000h jz @0 invoke MessageBeep,0 invoke InvalidateRect,0,0,1 invoke ExitProcess,eax end start