Можно ли добавить прослушиватель событий в пользовательскую строку заголовка, используемую для перетаскивания окна в безрамочном окне?

В безрамочное окно добавлена ​​настраиваемая строка заголовка, чтобы окно можно было перетаскивать. Строка заголовка отображается, но eventListener не срабатывает:

основной.js:

const createWindow = () => {
    const win = new BrowserWindow({
      width: 800,
      height: 600,
      frame: false,
      scrollbar: false,
      webPreferences:{
        nodeIntegration: true,
        contextIsolation: false,
      }
    })
    win.loadFile('index.html')
  }

индекс.html:

<body>
  <div class = "window">
    <div class = "window-content">
      <textarea>some content</textarea>
    </div>
  </div>
  <script src = "index.js"></script>
</body>

индекс.js:

let titleBar = document.createElement('div')
titleBar.style.width = "100%"
titleBar.style.height = "32px"
titleBar.style.backgroundColor = "#fff"
titleBar.style.position = "absolute"
titleBar.style.top = titleBar.style.left = 0
titleBar.style.webkitAppRegion = "drag"
titleBar.textContent = 'My App';

document.body.appendChild(titleBar)

// Nothing happens
titleBar.addEventListener("mouseover", () => {
    console.info("hello")
})
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам не нужно использовать eventListener, вы можете добиться этого, используя только CSS.

main.js

const createWindow = () => {
const win = new BrowserWindow({
  width: 800,
  height: 600,
  frame: false,
  scrollbar: false,
  titleBarStyle: 'hidden',//Add this
  titleBarOverlay: {
   color: '#ecf2f9',
   symbolColor: '#003d99',
   height: 40,
  },//Add this for windows
  webPreferences:{
    nodeIntegration: true,
    contextIsolation: false,
  }
})
win.loadFile('index.html')
}

index.html

 <body>
<div class = "titleBar">
My App
</div>
<div class = "window">
  <div class = "window-content">
    <textarea>some content</textarea>
  </div>
</div>
<script src = "index.js"></script>

index.css

.titleBar{
background-color: #ecf2f9;
height: 40px; /* Adjust height as needed */
-webkit-app-region: drag; /*Allow dragging the window */
.
.
.
}

Большое спасибо за показ альтернативного способа создания пользовательской строки заголовка. Однако это также не позволяет обнаружить какие-либо прослушиватели событий. Итак, как говорит @oOosys, с перетаскиваемой строкой заголовка EventListeners кажется невозможным.

nBar 02.07.2024 11:26
Ответ принят как подходящий

Да, можно добавить прослушиватель событий в пользовательскую строку заголовка, используемую для перетаскивания окон в безрамочном окне, но для этого требуется реализация собственного кода событий мыши для перетаскивания окна.

Проблема с событиями мыши, не запускающими eventListener, вызвана

titleBar.style.webkitAppRegion = "drag"

что мешает механизму распространения событий и предотвращает обнаружение событий мыши прослушивателем.

Другими словами, кажется, что в Electron вы не можете одновременно использовать и то, и другое для одного и того же DOM-объекта: перетаскивание с помощью .style.webkitAppRegion = "drag" и получение событий мыши с помощью .addEventListener("mouseover",. Если вам нужно поведение перетаскивания, вам нужно реализовать его самостоятельно, используя события мыши, полученные от DOM-объекта.

Чтобы увидеть это самостоятельно, прокомментируйте или удалите строку «перетаскивания» и убедитесь, что событие мыши работает должным образом (не забывайте, что вывод консоли предоставляется после Ctrl+Shift+i в окне приложения, а не в окне приложения). Окно терминала, в котором запущено приложение).

Имейте в виду, что, используя некоторые «программные трюки», вы обычно можете достичь любого желаемого эффекта в любой программной системе, поэтому утверждения о том, что что-то невозможно, обычно не совсем корректны с этой точки зрения, поскольку они лишь утверждают, что не существует простого и хорошо известного способа достижения чего-либо.

Возможный обходной путь — иметь две строки заголовка (или значок перетаскивания рядом со строкой заголовка в одной строке): один для перетаскивания окна, а другой — для реагирования на события мыши:

console.info("renderer.js loaded");

document.addEventListener('DOMContentLoaded', () => {
    // Create the draggable title bar at the very top
    let draggableTitleBar = document.createElement('div');
    draggableTitleBar.style.width = "100%";
    draggableTitleBar.style.height = "24px";
    draggableTitleBar.style.backgroundColor = "#e74c3c";
    draggableTitleBar.style.position = "absolute";
    draggableTitleBar.style.top = "0px";
    draggableTitleBar.style.left = "0px";
    draggableTitleBar.style.zIndex = "1000";
    draggableTitleBar.style.webkitAppRegion = "drag";
    draggableTitleBar.textContent = 'Draggable Title Bar';

    // Create the non-draggable title bar below it
    let nonDraggableTitleBar = document.createElement('div');
    nonDraggableTitleBar.style.width = "100%";
    nonDraggableTitleBar.style.height = "40px";
    nonDraggableTitleBar.style.backgroundColor = "#3498db";
    nonDraggableTitleBar.style.position = "absolute";
    nonDraggableTitleBar.style.top = "24px"; // Adjust position as needed
    nonDraggableTitleBar.style.left = "0px";
    nonDraggableTitleBar.style.zIndex = "1000";
    nonDraggableTitleBar.textContent = 'Non-Draggable Title Bar';

    // Add event listeners to the non-draggable title bar
    nonDraggableTitleBar.addEventListener("mouseover", () => {
        console.info("Mouseover event triggered on non-draggable title bar");
    });

    nonDraggableTitleBar.addEventListener("click", () => {
        console.info("Non-draggable title bar clicked");
    });

    // Append both title bars to the document body
    document.body.appendChild(draggableTitleBar);
    document.body.appendChild(nonDraggableTitleBar);

    console.info("Title bars added to the DOM");
});

Вот как это выглядит:

Для полноты ниже приведен код приложения, которое использует строку заголовка как для перетаскивания окна, так и для приема событий мыши (записывается в консоль):


~ $ cat package.json 
{
    "name": "oOosysElectronApp",
    "version": "1.0.0",
    "main": "main.js",
    "scripts": {
        "start": "electron ."
    },
    "keywords": [],
    "author": "oOosys",
    "license": "---",
    "description": "PureGraphicWindowArea",
    "dependencies": {
        "electron": "^31.1.0"
    }
}
~ $ cat main.js
const { app, BrowserWindow, ipcMain } = require('electron');
// const path = require('path');

function createWindow() {
    const win = new BrowserWindow({
        width: 800,
        height: 480,
        frame: false,
        scrollbar: false,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
        }
    });

    win.loadFile('index.html');

    ipcMain.on('get-window-position', (event) => {
        event.returnValue = win.getPosition();
    });

    ipcMain.on('set-window-position', (event, x, y) => {
    // console.info("set-window-position to x,y : ", x , y) // prints to TERMINAL 
        win.setPosition(x, y);
    });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});
~ $ cat renderer.js
const { ipcRenderer } = require('electron');

console.info("renderer.js loaded");

document.addEventListener('DOMContentLoaded', () => {
    // Create the title bar
    let titleBar = document.createElement('div');
    titleBar.style.width = "100%";
    titleBar.style.height = "32px";
    titleBar.style.backgroundColor = "lightblue"; // Temporary background color for visibility
    titleBar.style.position = "absolute";
    titleBar.style.top = "0px";
    titleBar.style.left = "0px";
    titleBar.style.zIndex = "1000"; // Ensure the title bar is on top
    titleBar.textContent = 'Window Dragging Title';

    document.body.appendChild(titleBar);
    console.info("Title bar added to the DOM");

    let isDragging = false;
    let startX, startY;
    let startWindowX, startWindowY;

    titleBar.addEventListener("mousedown", (event) => {
        event.preventDefault();
        event.stopPropagation();
        isDragging = true;
        startX = event.clientX;
        startY = event.clientY;
        const [windowX, windowY] = ipcRenderer.sendSync('get-window-position');
        startWindowX = windowX;
        startWindowY = windowY;
        console.info("MouseDOWN windowX,Y, mouseX,Y:", startWindowX, startWindowY, startX, startY);
    });

    // mousemove event interferes somehow with 
    //          ipcRenderer.send('set-window-position', newWindowX, newWindowY);
    //      causing the window to resize instead of re-position
    // In other words CONTINUOUS DRAGGING of the window FAILS TO WORK as expected
    
    document.addEventListener("mouseup", (event) => {
        if ( isDragging ) {
            const currentX = event.clientX;
            const currentY = event.clientY;
            const deltaX = currentX - startX;
            const deltaY = currentY - startY;
            const newWindowX = startWindowX + deltaX;
            const newWindowY = startWindowY + deltaY;
            ipcRenderer.send('set-window-position', newWindowX, newWindowY);
            console.info("mouseUP newWindowX,Y mouseMovedDistXY:", newWindowX, newWindowY, deltaX, deltaY);
            isDragging = false;
        }
    });
});
~ $ cat index.html
<!DOCTYPE html>
<html><head><title>oOosys Electron App</title>
<style>
    body, html {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
         background-color: #d0eed0;
    }
</style></head>
<body>
    <script src = "renderer.js"></script>
    
    <br><br><br><br><br><br><br><br><br>
    <textarea>some content</textarea>
</body></html>
~ $ npm start 2>/dev/null

> [email protected] start
> electron .

А вот как это выглядит после выполнения кода, задокументированного в приведенном выше журнале сеанса оболочки:

Обратите внимание, что при событии mouseup окно перемещается в целевую позицию. Событие mousemove, похоже, мешает работе ipcRenderer.send('set-window-position', newWindowX, newWindowY);, что приводит к изменению размера окна вместо перемещения. поэтому этот подход, похоже, не может обеспечить плавное непрерывное перетаскивание окна из-за проблемы с функциональностью Electron.

Спасибо за обходной путь, но для меня это не вариант. Итак, в конце концов ответ (цитирую вас): «в Electron вы не можете одновременно иметь и то, и другое: перетаскивание и запуск событий мыши».

nBar 02.07.2024 11:29

@nBar: см. мой обновленный ответ, где приведен пример приложения, использующего строку заголовка для обеих целей: получения событий мыши и перетаскивания окна.

oOosys 02.07.2024 19:28

Это действительно обходной путь, который работает хорошо! Перетаскивание не совсем плавное, но работает. Таким образом, с вашим решением в Electron фактически возможно иметь перетаскиваемую настраиваемую строку заголовка, которая также может получать события мыши.

nBar 03.07.2024 21:42

Другие вопросы по теме

Навигация по страницам с помощью Nuxt3/Electron не работает – невозможно загружать локальный ресурс с помощью '#'
Почему шифрование выдает «ERR_CRYPTO_UNKNOWN_CIPHER» при использовании AES-KW в качестве алгоритма шифрования в основном процессе Electron?
Electron - приложение React __dirname не определено
Проверьте, работает ли какое-либо системное приложение в полноэкранном режиме nodeJS
Ошибка при попытке упаковать электронное приложение
Cypress — (неперехваченное исключение) NotSupportedError: пользовательский агент не поддерживает учетные данные открытого ключа
Электронный магазин возвращает «Свойство 'set'/'get' не существует по типу»
Как создать сценарий автозаполнения JavaScript для форм в Electron WebView, который обходит проблемы проверки?
При использовании Electron Forge + Vite + Selenium у меня возникла ошибка javaScript в основном процессе
Почему для моего оператора «includes» требуется вся строка?