И почему тогда этот пример только подтверждает изложенную мной "бредовую" концепцию? Зачем ты его привел?
Еще одно подтверждение бредовых концепций. Потому что вся ide буквально обертка на созданный другими компонент. Как тракторист, сидящий в тракторе.
Как сильно понизились ставки. То, что в одно лицо хотя бы выбор шрифта в программе можно реализовать - истина. Ты это только что убедительно доказал.
Можно и самому написать если руки не из задницы. Код (Pascal): program SimpleEditor; uses Windows, Messages, SysUtils; const MAX_LINES = 10000; MAX_COLS = 1000; CHAR_WIDTH = 8; CHAR_HEIGHT = 16; LINE_SPACING = 20; LEFT_MARGIN = 50; TOP_MARGIN = 10; SCROLLBAR_WIDTH = 20; LINE_NUMBER_WIDTH = 40; CURRENT_LINE_COLOR = $E8E8E8; type TCell = record Ch: Char; Attr: Byte; end; TEditorModel = record Cells: array[0..MAX_LINES - 1, 0..MAX_COLS - 1] of TCell; LineCount: Integer; CurLine, CurCol: Integer; end; TEditorView = record Handle: HWND; VScroll, HScroll: HWND; ScrollLine, ScrollCol: Integer; MaxScrollLine, MaxScrollCol: Integer; Width, Height: Integer; end; var Model: TEditorModel; View: TEditorView; Msg: TMsg; // ==================== ВСПОМОГАТЕЛЬНЫЕ ==================== function GetLineLen(Line: Integer): Integer; begin Result := 0; while (Result < MAX_COLS) and (Model.Cells[Line, Result].Ch <> #0) do Inc(Result); end; function GetVisibleLines: Integer; var ClientRect: TRect; begin GetClientRect(View.Handle, ClientRect); Result := (ClientRect.Bottom - ClientRect.Top - TOP_MARGIN) div LINE_SPACING; if Result < 1 then Result := 1; end; function GetVisibleCols: Integer; var ClientRect: TRect; begin GetClientRect(View.Handle, ClientRect); Result := (ClientRect.Right - ClientRect.Left - LEFT_MARGIN - SCROLLBAR_WIDTH) div CHAR_WIDTH; if Result < 1 then Result := 1; end; procedure UpdateScrollRanges; var i, MaxLineLen: Integer; VisibleLines, VisibleCols: Integer; si: TScrollInfo; begin VisibleLines := GetVisibleLines; VisibleCols := GetVisibleCols; MaxLineLen := 0; for i := 0 to Model.LineCount - 1 do begin if GetLineLen(i) > MaxLineLen then MaxLineLen := GetLineLen(i); end; if Model.LineCount > VisibleLines then View.MaxScrollLine := Model.LineCount - VisibleLines else View.MaxScrollLine := 0; if View.ScrollLine > View.MaxScrollLine then View.ScrollLine := View.MaxScrollLine; if View.ScrollLine < 0 then View.ScrollLine := 0; si.cbSize := SizeOf(si); si.fMask := SIF_RANGE or SIF_PAGE or SIF_POS; si.nMin := 0; si.nMax := Model.LineCount - 1; si.nPage := VisibleLines; si.nPos := View.ScrollLine; SetScrollInfo(View.VScroll, SB_CTL, si, True); if MaxLineLen > VisibleCols then View.MaxScrollCol := MaxLineLen - VisibleCols else View.MaxScrollCol := 0; if View.ScrollCol > View.MaxScrollCol then View.ScrollCol := View.MaxScrollCol; if View.ScrollCol < 0 then View.ScrollCol := 0; si.fMask := SIF_RANGE or SIF_PAGE or SIF_POS; si.nMin := 0; si.nMax := MaxLineLen; si.nPage := VisibleCols; si.nPos := View.ScrollCol; SetScrollInfo(View.HScroll, SB_CTL, si, True); end; procedure UpdateCaret; begin SetCaretPos(LEFT_MARGIN + (Model.CurCol - View.ScrollCol) * CHAR_WIDTH, TOP_MARGIN + (Model.CurLine - View.ScrollLine) * LINE_SPACING); end; procedure UpdateWindowTitle; var Title: string; begin Title := Format('Editor - Line: %d, Col: %d', [Model.CurLine + 1, Model.CurCol + 1]); SetWindowText(View.Handle, PChar(Title)); end; procedure ScrollToCursor; var VisibleLines, VisibleCols: Integer; begin VisibleLines := GetVisibleLines; VisibleCols := GetVisibleCols; if Model.CurLine < View.ScrollLine then View.ScrollLine := Model.CurLine else if Model.CurLine >= View.ScrollLine + VisibleLines then View.ScrollLine := Model.CurLine - VisibleLines + 1; if Model.CurCol < View.ScrollCol then View.ScrollCol := Model.CurCol else if Model.CurCol >= View.ScrollCol + VisibleCols then View.ScrollCol := Model.CurCol - VisibleCols + 1; UpdateScrollRanges; InvalidateRect(View.Handle, nil, True); UpdateWindowTitle; end; // ==================== ОПЕРАЦИИ ==================== procedure InsertChar(ch: Char); var i, Len: Integer; begin Len := GetLineLen(Model.CurLine); if Len >= MAX_COLS - 1 then Exit; for i := Len downto Model.CurCol + 1 do Model.Cells[Model.CurLine, i] := Model.Cells[Model.CurLine, i - 1]; Model.Cells[Model.CurLine, Model.CurCol].Ch := ch; Inc(Model.CurCol); ScrollToCursor; UpdateCaret; InvalidateRect(View.Handle, nil, True); end; procedure NewLine; var i, j: Integer; Len: Integer; begin if Model.LineCount >= MAX_LINES then Exit; Len := GetLineLen(Model.CurLine); for i := Model.LineCount downto Model.CurLine + 2 do begin for j := 0 to MAX_COLS - 1 do Model.Cells[i, j] := Model.Cells[i - 1, j]; end; for j := Model.CurCol to Len - 1 do Model.Cells[Model.CurLine + 1, j - Model.CurCol] := Model.Cells[Model.CurLine, j]; for j := Model.CurCol to Len - 1 do Model.Cells[Model.CurLine, j].Ch := #0; Inc(Model.LineCount); Inc(Model.CurLine); Model.CurCol := 0; ScrollToCursor; UpdateCaret; InvalidateRect(View.Handle, nil, True); end; procedure DeleteChar; var i, j, Len: Integer; begin if Model.CurCol > 0 then begin Len := GetLineLen(Model.CurLine); for i := Model.CurCol to Len - 1 do Model.Cells[Model.CurLine, i - 1] := Model.Cells[Model.CurLine, i]; Dec(Model.CurCol); Model.Cells[Model.CurLine, Len - 1].Ch := #0; InvalidateRect(View.Handle, nil, True); end else if Model.CurLine > 0 then begin Model.CurCol := GetLineLen(Model.CurLine - 1); for i := 0 to GetLineLen(Model.CurLine) - 1 do Model.Cells[Model.CurLine - 1, Model.CurCol + i] := Model.Cells[Model.CurLine, i]; for i := Model.CurLine to Model.LineCount - 2 do begin for j := 0 to MAX_COLS - 1 do Model.Cells[i, j] := Model.Cells[i + 1, j]; end; Dec(Model.LineCount); for i := 0 to MAX_COLS - 1 do Model.Cells[Model.LineCount, i].Ch := #0; Dec(Model.CurLine); ScrollToCursor; InvalidateRect(View.Handle, nil, True); end; UpdateCaret; end; procedure DeleteCharRight; var i, j, Len: Integer; begin if Model.CurCol < GetLineLen(Model.CurLine) then begin Len := GetLineLen(Model.CurLine); for i := Model.CurCol + 1 to Len - 1 do Model.Cells[Model.CurLine, i - 1] := Model.Cells[Model.CurLine, i]; Model.Cells[Model.CurLine, Len - 1].Ch := #0; InvalidateRect(View.Handle, nil, True); end else if Model.CurLine + 1 < Model.LineCount then begin Len := GetLineLen(Model.CurLine); for i := 0 to GetLineLen(Model.CurLine + 1) - 1 do Model.Cells[Model.CurLine, Len + i] := Model.Cells[Model.CurLine + 1, i]; for i := Model.CurLine + 1 to Model.LineCount - 2 do begin for j := 0 to MAX_COLS - 1 do Model.Cells[i, j] := Model.Cells[i + 1, j]; end; Dec(Model.LineCount); for i := 0 to MAX_COLS - 1 do Model.Cells[Model.LineCount, i].Ch := #0; InvalidateRect(View.Handle, nil, True); end; UpdateCaret; end; procedure InsertTab; var i: Integer; begin for i := 1 to 4 do InsertChar(' '); end; procedure MoveCursor(Line, Col: Integer); begin if Line < 0 then Line := 0; if Line >= Model.LineCount then Line := Model.LineCount - 1; if Col < 0 then Col := 0; if Col > GetLineLen(Line) then Col := GetLineLen(Line); Model.CurLine := Line; Model.CurCol := Col; ScrollToCursor; UpdateCaret; UpdateWindowTitle; end; // ==================== ОТРИСОВКА ==================== procedure HighlightCurrentLine(dc: HDC); var Rect: TRect; CurrentLineVisible: Integer; begin if (Model.CurLine < View.ScrollLine) or (Model.CurLine >= View.ScrollLine + GetVisibleLines) then Exit; CurrentLineVisible := Model.CurLine - View.ScrollLine; Rect.Left := 0; Rect.Top := TOP_MARGIN + CurrentLineVisible * LINE_SPACING; Rect.Right := View.Width - SCROLLBAR_WIDTH; Rect.Bottom := Rect.Top + CHAR_HEIGHT; SetBkColor(dc, CURRENT_LINE_COLOR); ExtTextOut(dc, 0, 0, ETO_OPAQUE, @Rect, nil, 0, nil); end; procedure DrawLineNumbers(dc: HDC); var i, Y: Integer; StartLine, EndLine: Integer; VisibleLines: Integer; NumberStr: string; OldBkMode: Integer; OldTextColor: COLORREF; begin VisibleLines := GetVisibleLines; StartLine := View.ScrollLine; EndLine := StartLine + VisibleLines; if EndLine > Model.LineCount then EndLine := Model.LineCount; OldBkMode := SetBkMode(dc, TRANSPARENT); OldTextColor := SetTextColor(dc, RGB(100, 100, 100)); Y := TOP_MARGIN; for i := StartLine to EndLine - 1 do begin NumberStr := IntToStr(i + 1); TextOut(dc, LEFT_MARGIN - LINE_NUMBER_WIDTH + 5, Y, PChar(NumberStr), Length(NumberStr)); Y := Y + LINE_SPACING; end; SetBkMode(dc, OldBkMode); SetTextColor(dc, OldTextColor); end; procedure DrawText(dc: HDC); var i, j, X, Y: Integer; StartLine, EndLine: Integer; VisibleCols: Integer; begin StartLine := View.ScrollLine; EndLine := StartLine + GetVisibleLines; if EndLine > Model.LineCount then EndLine := Model.LineCount; VisibleCols := GetVisibleCols; Y := TOP_MARGIN; for i := StartLine to EndLine - 1 do begin X := LEFT_MARGIN; for j := View.ScrollCol to View.ScrollCol + VisibleCols - 1 do begin if Model.Cells[i, j].Ch <> #0 then begin SetTextColor(dc, RGB(0, 0, 0)); SetBkColor(dc, RGB(255, 255, 255)); TextOut(dc, X, Y, @Model.Cells[i, j].Ch, 1); end; Inc(X, CHAR_WIDTH); end; Inc(Y, LINE_SPACING); end; end; procedure DrawAll(dc: HDC); begin HighlightCurrentLine(dc); DrawLineNumbers(dc); DrawText(dc); end; // ==================== ОБРАБОТЧИКИ ==================== procedure OnPaint; var ps: TPaintStruct; dc: HDC; Font: HFONT; OldFont: HFONT; begin dc := BeginPaint(View.Handle, ps); Font := CreateFont(CHAR_HEIGHT, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH or FF_MODERN, 'Courier New'); OldFont := SelectObject(dc, Font); DrawAll(dc); SelectObject(dc, OldFont); DeleteObject(Font); EndPaint(View.Handle, ps); end; procedure OnVScroll(wParam: WPARAM); var si: TScrollInfo; NewPos: Integer; begin si.cbSize := SizeOf(si); si.fMask := SIF_ALL; GetScrollInfo(View.VScroll, SB_CTL, si); case LoWord(wParam) of SB_LINEUP: NewPos := View.ScrollLine - 1; SB_LINEDOWN: NewPos := View.ScrollLine + 1; SB_PAGEUP: NewPos := View.ScrollLine - GetVisibleLines; SB_PAGEDOWN: NewPos := View.ScrollLine + GetVisibleLines; SB_THUMBTRACK: NewPos := si.nTrackPos; else Exit; end; if NewPos < 0 then NewPos := 0; if NewPos > View.MaxScrollLine then NewPos := View.MaxScrollLine; if NewPos <> View.ScrollLine then begin View.ScrollLine := NewPos; UpdateScrollRanges; InvalidateRect(View.Handle, nil, True); UpdateCaret; end; end; procedure OnHScroll(wParam: WPARAM); var si: TScrollInfo; NewPos: Integer; begin si.cbSize := SizeOf(si); si.fMask := SIF_ALL; GetScrollInfo(View.HScroll, SB_CTL, si); case LoWord(wParam) of SB_LINELEFT: NewPos := View.ScrollCol - 1; SB_LINERIGHT: NewPos := View.ScrollCol + 1; SB_PAGELEFT: NewPos := View.ScrollCol - GetVisibleCols; SB_PAGERIGHT: NewPos := View.ScrollCol + GetVisibleCols; SB_THUMBTRACK: NewPos := si.nTrackPos; else Exit; end; if NewPos < 0 then NewPos := 0; if NewPos > View.MaxScrollCol then NewPos := View.MaxScrollCol; if NewPos <> View.ScrollCol then begin View.ScrollCol := NewPos; UpdateScrollRanges; InvalidateRect(View.Handle, nil, True); UpdateCaret; end; end; procedure OnMouseDown(X, Y: Integer); var ClickedLine, ClickedCol: Integer; begin SetFocus(View.Handle); if X < LEFT_MARGIN - LINE_NUMBER_WIDTH then begin ClickedLine := View.ScrollLine + (Y - TOP_MARGIN) div LINE_SPACING; if ClickedLine < 0 then ClickedLine := 0; if ClickedLine >= Model.LineCount then ClickedLine := Model.LineCount - 1; MoveCursor(ClickedLine, 0); Exit; end; ClickedLine := View.ScrollLine + (Y - TOP_MARGIN) div LINE_SPACING; if ClickedLine < 0 then ClickedLine := 0; if ClickedLine >= Model.LineCount then ClickedLine := Model.LineCount - 1; ClickedCol := View.ScrollCol + (X - LEFT_MARGIN) div CHAR_WIDTH; if ClickedCol < 0 then ClickedCol := 0; MoveCursor(ClickedLine, ClickedCol); end; procedure OnChar(wParam: WPARAM); begin case wParam of 8: DeleteChar; 13: NewLine; 9: InsertTab; else if wParam >= 32 then InsertChar(Char(wParam)); end; UpdateCaret; end; procedure OnKeyDown(wParam: WPARAM); begin case wParam of VK_LEFT: MoveCursor(Model.CurLine, Model.CurCol - 1); VK_RIGHT: MoveCursor(Model.CurLine, Model.CurCol + 1); VK_UP: MoveCursor(Model.CurLine - 1, Model.CurCol); VK_DOWN: MoveCursor(Model.CurLine + 1, Model.CurCol); VK_HOME: MoveCursor(Model.CurLine, 0); VK_END: MoveCursor(Model.CurLine, GetLineLen(Model.CurLine)); VK_DELETE: DeleteCharRight; end; UpdateCaret; end; // ==================== ОКОННАЯ ПРОЦЕДУРА ==================== function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; var i, j: Integer; begin Result := 0; case Msg of WM_CREATE: begin View.Handle := hWnd; Model.LineCount := 1; for i := 0 to MAX_LINES - 1 do for j := 0 to MAX_COLS - 1 do Model.Cells[i, j].Ch := #0; Model.CurLine := 0; Model.CurCol := 0; View.ScrollLine := 0; View.ScrollCol := 0; View.VScroll := CreateWindow('SCROLLBAR', nil, WS_CHILD or WS_VISIBLE or SBS_VERT, 0, 0, SCROLLBAR_WIDTH, 0, hWnd, 0, HInstance, nil); View.HScroll := CreateWindow('SCROLLBAR', nil, WS_CHILD or WS_VISIBLE or SBS_HORZ, 0, 0, 0, SCROLLBAR_WIDTH, hWnd, 0, HInstance, nil); UpdateScrollRanges; UpdateWindowTitle; Result := 0; end; WM_SIZE: begin View.Width := LOWORD(lParam); View.Height := HIWORD(lParam); MoveWindow(View.VScroll, View.Width - SCROLLBAR_WIDTH, 0, SCROLLBAR_WIDTH, View.Height - SCROLLBAR_WIDTH, True); MoveWindow(View.HScroll, 0, View.Height - SCROLLBAR_WIDTH, View.Width - SCROLLBAR_WIDTH, SCROLLBAR_WIDTH, True); UpdateScrollRanges; InvalidateRect(hWnd, nil, True); Result := 0; end; WM_VSCROLL: OnVScroll(wParam); WM_HSCROLL: OnHScroll(wParam); WM_PAINT: OnPaint; WM_LBUTTONDOWN: OnMouseDown(LOWORD(lParam), HIWORD(lParam)); WM_SETFOCUS: begin CreateCaret(hWnd, 0, 2, CHAR_HEIGHT); ShowCaret(hWnd); UpdateCaret; Result := 0; end; WM_KILLFOCUS: begin HideCaret(hWnd); DestroyCaret; Result := 0; end; WM_CHAR: OnChar(wParam); WM_KEYDOWN: OnKeyDown(wParam); WM_DESTROY: begin PostQuitMessage(0); Result := 0; end; else Result := DefWindowProc(hWnd, Msg, wParam, lParam); end; end; // ==================== ТОЧКА ВХОДА ==================== var WC: TWndClass; begin FillChar(WC, SizeOf(WC), 0); WC.style := CS_HREDRAW or CS_VREDRAW; WC.lpfnWndProc := @WndProc; WC.hInstance := HInstance; WC.hbrBackground := GetStockObject(WHITE_BRUSH); WC.lpszClassName := 'SimpleEditor'; Windows.RegisterClass(WC); View.Handle := CreateWindow('SimpleEditor', 'Simple Editor', WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN, 230, 100, 800, 600, 0, 0, HInstance, nil); if View.Handle = 0 then Halt(1); ShowWindow(View.Handle, SW_SHOW); UpdateWindow(View.Handle); while GetMessage(Msg, 0, 0, 0) do begin TranslateMessage(Msg); DispatchMessage(Msg); end; end.
Я напоминаю, что ты споришь с тезисом о том, что в одно лицо без заимствования чужого кода нельзя создать программу, не уступающую существующим аналогам. Судя по размеру исполняемого файла и тому, что он написан на дельфи - это что-то около хеловорлда.
Покажи пальцем, что в этом хеловролде заимствовано из чужого кода? Код (Pascal): type TCell = record Ch: Char; Attr: Byte; end; TEditorModel = record Cells: array[0..MAX_LINES - 1, 0..MAX_COLS - 1] of TCell; LineCount: Integer; CurLine, CurCol: Integer; end; TEditorView = record Handle: HWND; VScroll, HScroll: HWND; ScrollLine, ScrollCol: Integer; MaxScrollLine, MaxScrollCol: Integer; Width, Height: Integer; end; Эти структуры я сам придумывал.
Давай помогу с формальной логикой: здесь три критерия, объединенных конъюнкцией: A = B & C & D Я сделал предположение, что критерий D не выполняется. Указал на это.
Анализ. Сам код: Становится ясно почему юный пациент не может использовать диз/отладчик, там непонятное
Не знаю относится ли к глубоким знаниям апи то, что поля left и top здесь всегда будут нулю равны: Код (Text): GetClientRect(View.Handle, ClientRect); Result := (ClientRect.Right - ClientRect.Left - LEFT_MARGIN - SCROLLBAR_WIDTH) div CHAR_WIDTH; Никогда не устану удивляться крутизне этого компилера, он буквально вычитает сначала LEFT_MARGIN, затем SCROLLBAR_WIDTH: Код (Text): 00408452 E8 21C6FFFF call <JMP.&GetClientRect> 00408457 8B4424 08 mov eax,dword ptr ss:[esp+8] 0040845B 2B0424 sub eax,dword ptr ss:[esp] 0040845E 83E8 32 sub eax,32 00408461 83E8 14 sub eax,14 RGB это вызов процедуры. Константа? Хреностанта! Работает лучший и самый скорострельный компилер современности, ему лучше знать: Код (Text): SetBkColor(dc, RGB(255, 255, 255)); Код (Text): 00408DEC B1 FF mov cl,FF 00408DEE B2 FF mov dl,FF 00408DF0 B0 FF mov al,FF 00408DF2 E8 1DBDFFFF call <main.sub_404B14> 00408DF7 50 push eax 00408DF8 55 push ebp 00408DF9 E8 1ABCFFFF call <JMP.&SetBkColor> Классика, два соседних паттерна. Даже лишний префикс в предыдущей инструкции не повод не пихнуть еще одну, обрубив старшие поля еще раз для надежности: Код (Text): 004078CD 8BD0 mov edx,eax 004078CF 66:81E2 FF03 and dx,3FF 004078D4 0FB7D2 movzx edx,dx 004078D7 8915 40B74000 mov dword ptr ds:[40B740],edx Тут просто немая сцена: Код (Text): 0040933B 33C0 xor eax,eax 0040933D A3 A0B74000 mov dword ptr ds:[40B7A0],eax 00409342 33C0 xor eax,eax 00409344 A3 A4B74000 mov dword ptr ds:[40B7A4],eax 00409349 33C0 xor eax,eax 0040934B A3 B4B74000 mov dword ptr ds:[40B7B4],eax 00409350 33C0 xor eax,eax 00409352 A3 B8B74000 mov dword ptr ds:[40B7B8],eax --- Сообщение объединено, 17 июн 2026 в 23:02 --- Точно помню, что студия еще в начале десятых видела константы например, закостыливая их всячески. Стык между паттернами конъюнкции и преобразования типов тоже отработала бы как надо. Так что нет, с нормальным компилером такого не надо делать.
Я предполагаю что это демка а не готовый проект в прод. Код (Pascal): array[0..MAX_LINES - 1, 0..MAX_COLS - 1] Такие вещи динамически создаются в той же scintill'e. Ты прав. В этой паскалевой демке даже выделения текста нет. И .asm файлы она не компилирует в отличии от vscode. Нормальные люди такие вещи на асме пишут(на том же фасме), чтобы не было такого вопиющего фуфла в инструкциях. P. S. лично мне понятно, что имел в виду автор улетевший в бан.
Точно помню, что студия еще в начале десятых нормально костылила константы, что в выражениях, что пропуская вызовы функций. И стык между паттернами конъюнкции и преобразования типа тоже отработала бы правильно. Так что нет, с нормальным компилятором такого не надо делать.
Может какую нибудь демку сам напишешь? Чтобы быстрее свою мысль донести? Не нужен будет бред из булевой логики и портянки .асм листингов.
Судя по всему есть, но вот такой слабенький. Прямо мешанины из паттернов как у gcc там нету. Какую демку ты хочешь? Показать как вычитать одним приемом сумму из двух констант? Или как вызвать SetBkColor(dc, 0x00FFFFFF)?